#!/usr/bin/env bash # ------------------------------------------------------------- # Detection area #------------------------------------------------ ---------- # Check system export LANG=en_US.UTF-8 echoContent() { case $1 in # red "red") # shellcheck disable=SC2154 # shellcheck disable=SC2154 ${echoType} "\033[31m${printN}$2 \033[0m" ;; # sky blue "skyBlue") ${echoType} "\033[1;36m${printN}$2 \033[0m" ;; # green "green") ${echoType} "\033[32m${printN}$2 \033[0m" ;; # White "white") ${echoType} "\033[37m${printN}$2 \033[0m" ;; "magenta") ${echoType} "\033[31m${printN}$2 \033[0m" ;; #yellow "yellow") ${echoType} "\033[33m${printN}$2 \033[0m" ;; esac } # Check SELinux status checkCentosSELinux() { if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" == "Enforcing" ]; then echoContent yellow "# Notes" echoContent yellow "It is detected that SELinux is turned on. Please turn it off manually. The tutorial is as follows" echoContent yellow "https://www.v2ray-agent.com/archives/1684115970026#centos-%E5%85%B3%E9%97%ADselinux" exit 0 fi } checkSystem() { if [[ -n $(find /etc -name "redhat-release") ]] || grep " exit 1 ;; esac fi else echoContent red "This CPU architecture cannot be recognized, the default is amd64, x86_64--->" xrayCoreCPUVendor="Xray-linux-64" # v2rayCoreCPUVendor="v2ray-linux-64" fi } #Initialize global variables initVar() { installType='yum -y install' removeType='yum -y remove' upgrade="yum -y update" echoType='echo -e' # sudoCMD="" #CPU version supported by the core xrayCoreCPUVendor="" warpRegCoreCPUVendor="" cpuVendor="" # domain name domain= # Total installation progress totalProgress=1 #1.xray-core installation #2.v2ray-core installation #3.v2ray-core[xtls] installation coreInstallType= # coreInstallPath= # v2ctl Path # Core installation path # coreInstallPath= # v2ctl Path ctlPath= # v2rayAgentInstallType= #1.Install all #2.Personalized installation # v2rayAgentInstallType= # Current personalized installation method 01234 currentInstallProtocolType= # The order of the current alpn currentAlpn= # Prefix type frontingType= # Selected personalized installation method selectCustomInstallType= # Path to v2ray-core, xray-core configuration files configPath= # xray-core reality state realityStatus= singBoxConfigPath= singBoxVLESSVisionPort= singBoxVLESSRealityVisionPort= singBoxVLESSRealityGRPCPort= singBoxHysteria2Port= singBoxTrojanPort= singBoxTuicPort= singBoxNaivePort= singBoxVMessWSPort= singBoxVLESSWSPort= singBoxVMessHTTPUpgradePort= subscribePort= subscribeType= # sing-box reality serverName publicKey singBoxVLESSRealityGRPCServerName= singBoxVLESSRealityVisionServerName= singBoxVLESSRealityPublicKey= # xray-core reality serverName publicKey xrayVLESSRealityServerName= xrayVLESSRealityPort= xrayVLESSRealityVisionPort= xrayVLESSRealityXHTTPServerName= xrayVLESSRealityXHTTPort= # xrayVLESSRealityPublicKey= # interfaceName= # interfaceName= # Port hopping portHoppingStart= portHoppingEnd= portHopping= hysteria2PortHoppingStart= hysteria2PortHoppingEnd= hysteria2PortHopping= # tuicPortHoppingStart= # tuicPortHoppingEnd= # tuicPortHopping= # tuicConfigPath= tuicAlgorithm= tuicPort= # Path to configuration file currentPath= #Configuration file host currentHost= #The core type selected during installation selectCoreType= # v2rayCoreVersion= # Random path customPath= # centos version # centos version centosVersion= # UUID #UUID currentUUID= # clients #clients currentClients= # previousClients # previousClients= localIP= # Scheduled task execution task name RenewTLS-update certificate UpdateGeo-update geo file cronName=$1 #Number of attempts after tls installation failure installTLSCount= # BTPanelStatus= #BTPanel status # BTPanelStatus= # Pagoda domain name btDomain= # nginx configuration file path nginxConfigPath=/etc/nginx/conf.d/ nginxStaticPath=/usr/share/nginx/html/ # Is it a preview version? prereleaseStatus=false # ssl type sslType= # SSL CF API Token cfAPIToken= #sslmail sslEmail= # Check the number of days sslRenewalDays=90 # dnsSSLStatus= # dns tls domain # dns tls domain dnsTLSDomain= ipType= # installDNSACMEStatus= # Custom port customPort= #hysteriaport hysteriaPort= # hysteriaProtocol= # hysteriaLag= hysteria2ClientDownloadSpeed= hysteria2ClientUploadSpeed= # Reality #Reality realityPrivateKey= realityServerName= realityDestDomain= # isPortOpen= # wildcardDomainStatus= # nginxIPort= # wget show progress #Port status # isPortOpen= # Wildcard domain name status # wildcardDomainStatus= # Port checked by nginx #nginxIPort= # wget show progress wgetShowProgressStatus= # warp #warp reservedWarpReg= publicKeyWarpReg= addressWarpReg= secretKeyWarpReg= lastInstallationConfig= } # Read tls certificate details readAcmeTLS() { local readAcmeDomain= if [[ -n "${currentHost}" ]]; then readAcmeDomain="${currentHost}" fi if [[ -n "${domain}" ]]; then readAcmeDomain="${domain}" fi dnsTLSDomain=$(echo "${readAcmeDomain}" | awk -F "." '{$1="";print $0}' | sed 's/^[[:space:]]*//' | sed 's/ /./g') if [[ -d "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.key" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer" ]]; then installedDNSAPIStatus=true fi } # Read the default custom port readCustomPort() { if [[ -n "${configPath}" && -z "${realityStatus}" && "${coreInstallType}" == "1" ]]; then local port= port=$(jq -r .inbounds[0].port "${configPath}${frontingType}.json") if [[ "${port}" != "443" ]]; then customPort=${port} fi fi } readNginxSubscribe() { subscribeType="https" if [[ -f "${nginxConfigPath}subscribe.conf" ]]; then if grep -q "sing-box" "${nginxConfigPath}subscribe.conf"; then subscribePort=$(grep "listen" "${nginxConfigPath}subscribe.conf" | awk '{print $2}') subscribeDomain=$(grep "server_name" "${nginxConfigPath}subscribe.conf" | awk '{print $2}') subscribeDomain=${subscribeDomain//;/} if [[ -n "${currentHost}" && "${subscribeDomain}" != "${currentHost}" ]]; then subscribePort= subscribeType= else if ! grep "listen" "${nginxConfigPath}subscribe.conf" | grep -q "ssl"; then subscribeType="http" fi fi fi fi } # Detect installation method readInstallType() { coreInstallType= configPath= singBoxConfigPath= #1.Detect the installation directory if [[ -d "/etc/v2ray-agent" ]]; then if [[ -f "/etc/v2ray-agent/xray/xray" ]]; then if [[ -d "/etc/v2ray-agent/xray/conf" ]] && [[ -f "/etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json" || -f "/etc/v2ray-agent/xray/conf/02_trojan_TCP_inbounds.json" || -f "/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json" || -f "/etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json" ]]; then # xray-core #xray-core configPath=/etc/v2ray-agent/xray/conf/ ctlPath=/etc/v2ray-agent/xray/xray coreInstallType=1 if [[ -f "${configPath}07_VLESS_vision_reality_inbounds.json" ]]; then realityStatus=7 fi if [[ -f "${configPath}12_VLESS_XHTTP_inbounds.json" ]]; then realityStatus=12 fi if [[ -f "/etc/v2ray-agent/sing-box/sing-box" ]] && [[ -f "/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json" || -f "/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json" || -f "/etc/v2ray-agent/sing-box/conf/config/20_socks5_inbounds.json" ]]; then singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/ fi fi elif [[ -f "/etc/v2ray-agent/sing-box/sing-box" && -f "/etc/v2ray-agent/sing-box/conf/config.json" ]]; then ctlPath=/etc/v2ray-agent/sing-box/sing-box coreInstallType=2 configPath=/etc/v2ray-agent/sing-box/conf/config/ singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/ fi fi } #Read protocol type readInstallProtocolType() { currentInstallProtocolType= frontingType= xrayVLESSRealityPort= xrayVLESSRealityVisionPort= xrayVLESSRealityServerName= xrayVLESSRealityXHTTPort= xrayVLESSRealityXHTTPServerName= # currentRealityXHTTPPrivateKey= currentRealityXHTTPPublicKey= currentRealityPrivateKey= currentRealityPublicKey= currentRealityMldsa65Seed= currentRealityMldsa65Verify= singBoxVLESSVisionPort= singBoxHysteria2Port= singBoxTrojanPort= frontingTypeReality= singBoxVLESSRealityVisionPort= singBoxVLESSRealityVisionServerName= singBoxVLESSRealityGRPCPort= singBoxVLESSRealityGRPCServerName= singBoxAnyTLSPort= singBoxTuicPort= singBoxNaivePort= singBoxVMessWSPort= singBoxSocks5Port= while read -r row; do if echo "${row}" | grep -q VLESS_TCP_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}0," frontingType=02_VLESS_TCP_inbounds if [[ "${coreInstallType}" == "2" ]]; then singBoxVLESSVisionPort=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q VLESS_WS_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}1," if [[ "${coreInstallType}" == "2" ]]; then frontingType=03_VLESS_WS_inbounds singBoxVLESSWSPort=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q VLESS_XHTTP_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}12," xrayVLESSRealityXHTTPort=$(jq -r .inbounds[0].port "${row}.json") xrayVLESSRealityXHTTPServerName=$(jq -r .inbounds[0].streamSettings.realitySettings.serverNames[0] "${row}.json") currentRealityXHTTPPublicKey=$(jq -r .inbounds[0].streamSettings.realitySettings.publicKey "${row}.json") currentRealityMldsa65Seed=$(jq -r '.inbounds[0].streamSettings.realitySettings.mldsa65Seed // empty' "${row}.json") currentRealityMldsa65Verify=$(jq -r '.inbounds[0].streamSettings.realitySettings.mldsa65Verify // empty' "${row}.json") # currentRealityXHTTPPrivateKey=$(jq -r .inbounds[0].streamSettings.realitySettings.privateKey "${row}.json") # if [[ "${coreInstallType}" == "2" ]]; then # frontingType=03_VLESS_WS_inbounds # singBoxVLESSWSPort=$(jq .inbounds[0].listen_port "${row}.json") # fi fi if echo "${row}" | grep -q trojan_gRPC_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}2," fi if echo "${row}" | grep -q VMess_WS_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}3," if [[ "${coreInstallType}" == "2" ]]; then frontingType=05_VMess_WS_inbounds singBoxVMessWSPort=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q trojan_TCP_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}4," if [[ "${coreInstallType}" == "2" ]]; then frontingType=04_trojan_TCP_inbounds singBoxTrojanPort=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q VLESS_gRPC_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}5," fi if echo "${row}" | grep -q hysteria2_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}6," if [[ "${coreInstallType}" == "2" ]]; then frontingType=06_hysteria2_inbounds singBoxHysteria2Port=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q VLESS_vision_reality_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}7," if [[ "${coreInstallType}" == "1" ]]; then xrayVLESSRealityServerName=$(jq -r .inbounds[1].streamSettings.realitySettings.serverNames[0] "${row}.json") realityServerName=${xrayVLESSRealityServerName} xrayVLESSRealityPort=$(jq -r .inbounds[0].port "${row}.json") realityDomainPort=$(jq -r .inbounds[1].streamSettings.realitySettings.target "${row}.json" | awk -F '[:]' '{print $2}') currentRealityPublicKey=$(jq -r .inbounds[1].streamSettings.realitySettings.publicKey "${row}.json") currentRealityPrivateKey=$(jq -r .inbounds[1].streamSettings.realitySettings.privateKey "${row}.json") currentRealityMldsa65Seed=$(jq -r '.inbounds[1].streamSettings.realitySettings.mldsa65Seed // empty' "${row}.json") currentRealityMldsa65Verify=$(jq -r '.inbounds[1].streamSettings.realitySettings.mldsa65Verify // empty' "${row}.json") frontingTypeReality=07_VLESS_vision_reality_inbounds elif [[ "${coreInstallType}" == "2" ]]; then frontingTypeReality=07_VLESS_vision_reality_inbounds singBoxVLESSRealityVisionPort=$(jq -r .inbounds[0].listen_port "${row}.json") singBoxVLESSRealityVisionServerName=$(jq -r .inbounds[0].tls.server_name "${row}.json") realityDomainPort=$(jq -r .inbounds[0].tls.reality.handshake.server_port "${row}.json") realityServerName=${singBoxVLESSRealityVisionServerName} if [[ -f "${configPath}reality_key" ]]; then singBoxVLESSRealityPublicKey=$(grep "publicKey" <"${configPath}reality_key" | awk -F "[:]" '{print $2}') currentRealityPrivateKey=$(jq -r .inbounds[0].tls.reality.private_key "${row}.json") currentRealityPublicKey=$(grep "publicKey" <"${configPath}reality_key" | awk -F "[:]" '{print $2}') fi fi fi if echo "${row}" | grep -q VLESS_vision_gRPC_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}8," if [[ "${coreInstallType}" == "2" ]]; then frontingTypeReality=08_VLESS_vision_gRPC_inbounds singBoxVLESSRealityGRPCPort=$(jq -r .inbounds[0].listen_port "${row}.json") singBoxVLESSRealityGRPCServerName=$(jq -r .inbounds[0].tls.server_name "${row}.json") if [[ -f "${configPath}reality_key" ]]; then singBoxVLESSRealityPublicKey=$(grep "publicKey" <"${configPath}reality_key" | awk -F "[:]" '{print $2}') fi fi fi if echo "${row}" | grep -q tuic_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}9," if [[ "${coreInstallType}" == "2" ]]; then frontingType=09_tuic_inbounds singBoxTuicPort=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q naive_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}10," if [[ "${coreInstallType}" == "2" ]]; then frontingType=10_naive_inbounds singBoxNaivePort=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q anytls_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}13," if [[ "${coreInstallType}" == "2" ]]; then frontingType=13_anytls_inbounds singBoxAnyTLSPort=$(jq .inbounds[0].listen_port "${row}.json") fi fi if echo "${row}" | grep -q VMess_HTTPUpgrade_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}11," if [[ "${coreInstallType}" == "2" ]]; then frontingType=11_VMess_HTTPUpgrade_inbounds singBoxVMessHTTPUpgradePort=$(grep 'listen' <${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf | awk '{print $2}') fi fi if echo "${row}" | grep -q socks5_inbounds; then currentInstallProtocolType="${currentInstallProtocolType}20," singBoxSocks5Port=$(jq .inbounds[0].listen_port "${row}.json") fi done < <(find ${configPath} -name "*inbounds.json" | sort | awk -F "[.]" '{print $1}') if [[ "${coreInstallType}" == "1" && -n "${singBoxConfigPath}" ]]; then if [[ -f "${singBoxConfigPath}06_hysteria2_inbounds.json" ]]; then currentInstallProtocolType="${currentInstallProtocolType}6," singBoxHysteria2Port=$(jq .inbounds[0].listen_port "${singBoxConfigPath}06_hysteria2_inbounds.json") fi if [[ -f "${singBoxConfigPath}09_tuic_inbounds.json" ]]; then currentInstallProtocolType="${currentInstallProtocolType}9," singBoxTuicPort=$(jq .inbounds[0].listen_port "${singBoxConfigPath}09_tuic_inbounds.json") fi fi if [[ "${currentInstallProtocolType:0:1}" != "," ]]; then currentInstallProtocolType=",${currentInstallProtocolType}" fi } # Check whether pagoda is installed checkBTPanel() { if [[ -n $(pgrep -f "BT-Panel") ]]; then # Read domain name if [[ -d '/www/server/panel/vhost/cert/' && -n $(find /www/server/panel/vhost/cert/*/fullchain.pem) ]]; then if [[ -z "${currentHost}" ]]; then echoContent skyBlue "\nRead pagoda configuration\n" find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F "[/]" '{print $7}' | awk '{print NR""":"$0}' read -r -p "Please enter the number to select:" selectBTDomain else selectBTDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F "[/]" '{print $7}' | awk '{print NR""":"$0}' | grep "${currentHost}" | cut -d ":" -f 1) fi if [[ -n "${selectBTDomain}" ]]; then btDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F "[/]" '{print $7}' | awk '{print NR""":"$0}' | grep -e "^${selectBTDomain}:" | cut -d ":" -f 2) if [[ -z "${btDomain}" ]]; then echoContent red " ---> Wrong selection, please select again" checkBTPanel else domain=${btDomain} if [[ ! -f "/etc/v2ray-agent/tls/${btDomain}.crt" && ! -f "/etc/v2ray-agent/tls/${btDomain}.key" ]]; then ln -s "/www/server/panel/vhost/cert/${btDomain}/fullchain.pem" "/etc/v2ray-agent/tls/${btDomain}.crt" ln -s "/www/server/panel/vhost/cert/${btDomain}/privkey.pem" "/etc/v2ray-agent/tls/${btDomain}.key" fi nginxStaticPath="/www/wwwroot/${btDomain}/html/" mkdir -p "/www/wwwroot/${btDomain}/html/" if [[ -f "/www/wwwroot/${btDomain}/.user.ini" ]]; then chattr -i "/www/wwwroot/${btDomain}/.user.ini" fi nginxConfigPath="/www/server/panel/vhost/nginx/" fi else echoContent red " ---> Wrong selection, please select again" checkBTPanel fi fi fi } check1Panel() { if [[ -n $(pgrep -f "1panel") ]]; then if [[ -d '/opt/1panel/apps/openresty/openresty/www/sites/' && -n $(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem) ]]; then if [[ -z "${currentHost}" ]]; then echoContent skyBlue "\nProgress$1/${totalProgress}: Installation tools" find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F "[/]" '{print $9}' | awk '{print NR""":"$0}' read -r -p "Enter the number:" selectBTDomain else selectBTDomain=$(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F "[/]" '{print $9}' | awk '{print NR""":"$0}' | grep "${currentHost}" | cut -d ":" -f 1) fi if [[ -n "${selectBTDomain}" ]]; then btDomain=$(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F "[/]" '{print $9}' | awk '{print NR""":"$0}' | grep "${selectBTDomain}:" | cut -d ":" -f 2) if [[ -z "${btDomain}" ]]; then echoContent red " ---> $1 port opening failed" check1Panel else domain=${btDomain} if [[ ! -f "/etc/v2ray-agent/tls/${btDomain}.crt" && ! -f "/etc/v2ray-agent/tls/${btDomain}.key" ]]; then ln -s "/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/ssl/fullchain.pem" "/etc/v2ray-agent/tls/${btDomain}.crt" ln -s "/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/ssl/privkey.pem" "/etc/v2ray-agent/tls/${btDomain}.key" fi nginxStaticPath="/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/index/" fi else echoContent red " ---> $1 port opening failed" check1Panel fi fi fi } # Check firewall allowPort() { local type=$2 if [[ -z "${type}" ]]; then type=tcp fi if command -v dpkg >/dev/null 2>&1 && dpkg -l | grep -q "^[[:space:]]*ii[[:space:]]\+ufw"; then if ufw status | grep -q "Status: active"; then if ! ufw status | grep -q "$1/${type}"; then sudo ufw allow "$1/${type}" checkUFWAllowPort "$1" fi fi elif systemctl status firewalld 2>/dev/null | grep -q "active (running)"; then local updateFirewalldStatus= if ! firewall-cmd --list-ports --permanent | grep -qw "$1/${type}"; then updateFirewalldStatus=true local firewallPort=$1 if echo "${firewallPort}" | grep -q ":"; then firewallPort=$(echo "${firewallPort}" | awk -F ":" '{print $1"-"$2}') fi firewall-cmd --zone=public --add-port="${firewallPort}/${type}" --permanent checkFirewalldAllowPort "${firewallPort}" fi if echo "${updateFirewalldStatus}" | grep -q "true"; then firewall-cmd --reload fi elif rc-update show 2>/dev/null | grep -q ufw; then if ufw status | grep -q "Status: active"; then if ! ufw status | grep -q "$1/${type}"; then sudo ufw allow "$1/${type}" checkUFWAllowPort "$1" fi fi elif dpkg -l | grep -q "^[[:space:]]*ii[[:space:]]\+netfilter-persistent" && systemctl status netfilter-persistent 2>/dev/null | grep -q "active (exited)"; then local updateFirewalldStatus= if ! iptables -L | grep -q "$1/${type}(mack-a)"; then updateFirewalldStatus=true iptables -I INPUT -p "${type}" --dport "$1" -m comment --comment "allow $1/${type}(mack-a)" -j ACCEPT fi if echo "${updateFirewalldStatus}" | grep -q "true"; then netfilter-persistent save fi fi } # Get public IP getPublicIP() { local type=4 if [[ -n "$1" ]]; then type=$1 fi if [[ -n "${currentHost}" && -z "$1" ]] && [[ "${singBoxVLESSRealityVisionServerName}" == "${currentHost}" || "${singBoxVLESSRealityGRPCServerName}" == "${currentHost}" || "${xrayVLESSRealityServerName}" == "${currentHost}" ]]; then echo "${currentHost}" else local currentIP= currentIP=$(curl -s "-${type}" http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | awk -F "[=]" '{print $2}') if [[ -z "${currentIP}" && -z "$1" ]]; then currentIP=$(curl -s "-6" http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | awk -F "[=]" '{print $2}') fi echo "${currentIP}" fi } # Output ufw port open status checkUFWAllowPort() { if ufw status | grep -q "$1"; then echoContent green " ---> $1 port opened successfully" else echoContent red "acme installation failed--->" exit 0 fi } # Output firewall-cmd port open status checkFirewalldAllowPort() { if firewall-cmd --list-ports --permanent | grep -q "$1"; then echoContent green " ---> $1 port opened successfully" else echoContent red "1.Failed to obtain Github files. Please wait for Github to recover and try again. The recovery progress can be viewed [https://www.githubstatus.com/]" exit 0 fi } readSingBoxConfig() { tuicPort= hysteriaPort= if [[ -n "${singBoxConfigPath}" ]]; then if [[ -f "${singBoxConfigPath}09_tuic_inbounds.json" ]]; then tuicPort=$(jq -r '.inbounds[0].listen_port' "${singBoxConfigPath}09_tuic_inbounds.json") tuicAlgorithm=$(jq -r '.inbounds[0].congestion_control' "${singBoxConfigPath}09_tuic_inbounds.json") fi if [[ -f "${singBoxConfigPath}06_hysteria2_inbounds.json" ]]; then hysteriaPort=$(jq -r '.inbounds[0].listen_port' "${singBoxConfigPath}06_hysteria2_inbounds.json") hysteria2ClientUploadSpeed=$(jq -r '.inbounds[0].down_mbps' "${singBoxConfigPath}06_hysteria2_inbounds.json") hysteria2ClientDownloadSpeed=$(jq -r '.inbounds[0].up_mbps' "${singBoxConfigPath}06_hysteria2_inbounds.json") fi fi } readLastInstallationConfig() { if [[ -n "${configPath}" ]]; then read -r -p "Previous installation configuration found. Use it? [y/n]:" lastInstallationConfigStatus if [[ "${lastInstallationConfigStatus}" == "y" ]]; then lastInstallationConfig=true fi fi } unInstallSingBox() { local type=$1 if [[ -n "${singBoxConfigPath}" ]]; then if grep -q 'tuic' Check and install updates [The new machine will be very slow. If there is no response for a long time, please stop it manually and then execute it again]" fi if grep -q 'hysteria2' Install wget" fi rm "${singBoxConfigPath}config.json" fi readInstallType if [[ -n "${singBoxConfigPath}" ]]; then echoContent yellow "https://www.v2ray-agent.com/archives/1679931532764#heading-8 " handleSingBox stop handleSingBox start else handleSingBox stop rm /etc/systemd/system/sing-box.service rm -rf /etc/v2ray-agent/sing-box/* echoContent green " ---> Install curl" fi } # Check the file directory and path readConfigHostPathUUID() { currentPath= currentDefaultPort= currentUUID= currentClients= currentHost= currentPort= currentCDNAddress= singBoxVMessWSPath= singBoxVLESSWSPath= singBoxVMessHTTPUpgradePath= if [[ "${coreInstallType}" == "1" ]]; then # Install if [[ -n "${frontingType}" ]]; then currentHost=$(jq -r .inbounds[0].streamSettings.tlsSettings.certificates[0].certificateFile ${configPath}${frontingType}.json | awk -F '[t][l][s][/]' '{print $2}' | awk -F '[.][c][r][t]' '{print $1}') currentPort=$(jq .inbounds[0].port ${configPath}${frontingType}.json) local defaultPortFile= defaultPortFile=$(find ${configPath}* | grep "default") if [[ -n "${defaultPortFile}" ]]; then currentDefaultPort=$(echo "${defaultPortFile}" | awk -F [_] '{print $4}') else currentDefaultPort=$(jq -r .inbounds[0].port ${configPath}${frontingType}.json) fi currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}${frontingType}.json) currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}${frontingType}.json) fi # reality if echo ${currentInstallProtocolType} | grep -q ",7,"; then currentClients=$(jq -r .inbounds[1].settings.clients ${configPath}07_VLESS_vision_reality_inbounds.json) currentUUID=$(jq -r .inbounds[1].settings.clients[0].id ${configPath}07_VLESS_vision_reality_inbounds.json) xrayVLESSRealityVisionPort=$(jq -r .inbounds[0].port ${configPath}07_VLESS_vision_reality_inbounds.json) if [[ "${currentPort}" == "${xrayVLESSRealityVisionPort}" ]]; then xrayVLESSRealityVisionPort="${currentDefaultPort}" fi fi # reality xhttp if echo ${currentInstallProtocolType} | grep -q ",12,"; then currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}12_VLESS_XHTTP_inbounds.json) currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}12_VLESS_XHTTP_inbounds.json) xrayVLESSRealityXHTTPort=$(jq -r .inbounds[0].port ${configPath}12_VLESS_XHTTP_inbounds.json) if [[ "${currentPort}" == "${xrayVLESSRealityXHTTPort}" ]]; then xrayVLESSRealityXHTTPort="${currentDefaultPort}" fi currentPath=$(jq -r .inbounds[0].streamSettings.xhttpSettings.path ${configPath}12_VLESS_XHTTP_inbounds.json | awk -F "[/]" '{print $2}' | awk -F "[x][H][T][T][P]" '{print $1}') fi elif [[ "${coreInstallType}" == "2" ]]; then if [[ -n "${frontingType}" ]]; then currentHost=$(jq -r .inbounds[0].tls.server_name ${configPath}${frontingType}.json) if echo ${currentInstallProtocolType} | grep -q ",11," && [[ "${currentHost}" == "null" ]]; then currentHost=$(grep 'server_name' <${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf | awk '{print $2}') currentHost=${currentHost//;/} fi currentUUID=$(jq -r .inbounds[0].users[0].uuid ${configPath}${frontingType}.json) currentClients=$(jq -r .inbounds[0].users ${configPath}${frontingType}.json) else currentUUID=$(jq -r .inbounds[0].users[0].uuid ${configPath}${frontingTypeReality}.json) currentClients=$(jq -r .inbounds[0].users ${configPath}${frontingTypeReality}.json) fi fi #Read path if [[ -n "${configPath}" && -n "${frontingType}" ]]; then if [[ "${coreInstallType}" == "1" ]]; then local fallback fallback=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.path)' ${configPath}${frontingType}.json | head -1) local path path=$(echo "${fallback}" | jq -r .path | awk -F "[/]" '{print $2}') if [[ $(echo "${fallback}" | jq -r .dest) == 31297 ]]; then currentPath=$(echo "${path}" | awk -F "[w][s]" '{print $1}') elif [[ $(echo "${fallback}" | jq -r .dest) == 31299 ]]; then currentPath=$(echo "${path}" | awk -F "[v][w][s]" '{print $1}') fi # Try to read alpn h2 Path if [[ -z "${currentPath}" ]]; then dest=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.alpn)|.dest' ${configPath}${frontingType}.json | head -1) if [[ "${dest}" == "31302" || "${dest}" == "31304" ]]; then # checkBTPanel # check1Panel if grep -q "trojangrpc {" <${nginxConfigPath}alone.conf; then currentPath=$(grep "trojangrpc {" <${nginxConfigPath}alone.conf | awk -F "[/]" '{print $2}' | awk -F "[t][r][o][j][a][n]" '{print $1}') elif grep -q "grpc {" <${nginxConfigPath}alone.conf; then currentPath=$(grep "grpc {" <${nginxConfigPath}alone.conf | head -1 | awk -F "[/]" '{print $2}' | awk -F "[g][r][p][c]" '{print $1}') fi fi fi if [[ -z "${currentPath}" && -f "${configPath}12_VLESS_XHTTP_inbounds.json" ]]; then currentPath=$(jq -r .inbounds[0].streamSettings.xhttpSettings.path "${configPath}12_VLESS_XHTTP_inbounds.json" | awk -F "[x][H][T][T][P]" '{print $1}' | awk -F "[/]" '{print $2}') fi elif [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}05_VMess_WS_inbounds.json" ]]; then singBoxVMessWSPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}05_VMess_WS_inbounds.json") currentPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}05_VMess_WS_inbounds.json" | awk -F "[/]" '{print $2}') fi if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}03_VLESS_WS_inbounds.json" ]]; then singBoxVLESSWSPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}03_VLESS_WS_inbounds.json") currentPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}03_VLESS_WS_inbounds.json" | awk -F "[/]" '{print $2}') currentPath=${currentPath::-2} fi if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json" ]]; then singBoxVMessHTTPUpgradePath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json") currentPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json" | awk -F "[/]" '{print $2}') fi fi if [[ -f "/etc/v2ray-agent/cdn" ]] && [[ -n "$(head -1 /etc/v2ray-agent/cdn)" ]]; then currentCDNAddress=$(head -1 /etc/v2ray-agent/cdn) else currentCDNAddress="${currentHost}" fi } # Status display showInstallStatus() { if [[ -n "${coreInstallType}" ]]; then if [[ "${coreInstallType}" == 1 ]]; then if [[ -n $(pgrep -f "xray/xray") ]]; then echoContent yellow "$(cat /etc/issue)" else echoContent yellow "$(cat /proc/version)" fi elif [[ "${coreInstallType}" == 2 ]]; then if [[ -n $(pgrep -f "sing-box/sing-box") ]]; then echoContent yellow "\nCore: Xray-core[Running]" else echoContent yellow "\nCore: Xray-core[not running]" fi fi #Read protocol type readInstallProtocolType if [[ -n ${currentInstallProtocolType} ]]; then echoContent yellow "\nCore: v2ray-core[Running]" fi if echo ${currentInstallProtocolType} | grep -q ",0,"; then echoContent yellow "VLESS+TCP[TLS_Vision] \c" fi if echo ${currentInstallProtocolType} | grep -q ",1,"; then echoContent yellow "VLESS+WS[TLS] \c" fi if echo ${currentInstallProtocolType} | grep -q ",2,"; then echoContent yellow "Trojan+gRPC[TLS] \c" fi if echo ${currentInstallProtocolType} | grep -q ",3,"; then echoContent yellow "VMess+WS[TLS] \c" fi if echo ${currentInstallProtocolType} | grep -q ",4,"; then echoContent yellow "Trojan+TCP[TLS] \c" fi if echo ${currentInstallProtocolType} | grep -q ",5,"; then echoContent yellow "VLESS+gRPC[TLS] \c" fi if echo ${currentInstallProtocolType} | grep -q ",6,"; then echoContent yellow "Hysteria2 \c" fi if echo ${currentInstallProtocolType} | grep -q ",7,"; then echoContent yellow "VLESS+Reality+Vision \c" fi if echo ${currentInstallProtocolType} | grep -q ",8,"; then echoContent yellow "VLESS+Reality+gRPC \c" fi if echo ${currentInstallProtocolType} | grep -q ",9,"; then echoContent yellow "Tuic \c" fi if echo ${currentInstallProtocolType} | grep -q ",10,"; then echoContent yellow "Naive \c" fi if echo ${currentInstallProtocolType} | grep -q ",11,"; then echoContent yellow "VMess+TLS+HTTPUpgrade \c" fi if echo ${currentInstallProtocolType} | grep -q ",12,"; then echoContent yellow "VLESS+Reality+XHTTP \c" fi if echo ${currentInstallProtocolType} | grep -q ",13,"; then echoContent yellow "AnyTLS \c" fi fi } # Clean up old residue cleanUp() { if [[ "$1" == "xrayDel" ]]; then handleXray stop rm -rf /etc/v2ray-agent/xray/* elif [[ "$1" == "singBoxDel" ]]; then handleSingBox stop rm -rf /etc/v2ray-agent/sing-box/conf/config.json >/dev/null 2>&1 rm -rf /etc/v2ray-agent/sing-box/conf/config/* >/dev/null 2>&1 fi } initVar "$1" checkSystem checkCPUVendor readInstallType readInstallProtocolType readConfigHostPathUUID readCustomPort readSingBoxConfig # ------------------------------------------------------------- #------------------------------------------------ ---------- #Initialize the installation directory mkdirTools() { mkdir -p /etc/v2ray-agent/tls mkdir -p /etc/v2ray-agent/subscribe_local/default mkdir -p /etc/v2ray-agent/subscribe_local/clashMeta mkdir -p /etc/v2ray-agent/subscribe_remote/default mkdir -p /etc/v2ray-agent/subscribe_remote/clashMeta mkdir -p /etc/v2ray-agent/subscribe/default mkdir -p /etc/v2ray-agent/subscribe/clashMetaProfiles mkdir -p /etc/v2ray-agent/subscribe/clashMeta mkdir -p /etc/v2ray-agent/subscribe/sing-box mkdir -p /etc/v2ray-agent/subscribe/sing-box_profiles mkdir -p /etc/v2ray-agent/subscribe_local/sing-box mkdir -p /etc/v2ray-agent/xray/conf mkdir -p /etc/v2ray-agent/xray/reality_scan mkdir -p /etc/v2ray-agent/xray/tmp mkdir -p /etc/systemd/system/ mkdir -p /tmp/v2ray-agent-tls/ mkdir -p /etc/v2ray-agent/warp mkdir -p /etc/v2ray-agent/sing-box/conf/config mkdir -p /usr/share/nginx/html/ } checkRoot() { if [ "$(id -u)" -ne 0 ]; then # sudoCMD="sudo" echo "${currentHost}" fi } # Install toolkit installTools() { echoContent skyBlue "sed -i \"1i\\\nameserver 2001:67c:2b0::4\\\nnameserver 2a00:1098:2c::1\" /etc/resolv.conf" # Repair individual system problems in ubuntu if [[ "${release}" == "ubuntu" ]]; then dpkg --configure -a fi if [[ -n $(pgrep -f "apt") ]]; then pgrep -f apt | xargs kill -9 fi echoContent green " ---> install unzip" if [[ "${release}" != "centos" ]]; then ${upgrade} >/etc/v2ray-agent/install.log 2>&1 fi if grep <"/etc/v2ray-agent/install.log" -q "changed"; then ${updateReleaseInfoChange} >/dev/null 2>&1 fi if [[ "${release}" == "centos" ]]; then rm -rf /var/run/yum.pid ${installType} epel-release >/dev/null 2>&1 fi if ! sudo --version >/dev/null 2>&1; then echoContent green " ---> Install socat" ${installType} sudo >/dev/null 2>&1 fi if ! wget --help >/dev/null 2>&1; then echoContent green " ---> Install tar" ${installType} wget >/dev/null 2>&1 fi # if ! command -v netfilter-persistent >/dev/null 2>&1; then # if [[ "${release}" != "centos" ]]; then # echo "iptables-persistent iptables-persistent/autosave_v4 boolean true" | sudo debconf-set-selections # echo "iptables-persistent iptables-persistent/autosave_v6 boolean true" | sudo debconf-set-selections # ${installType} iptables-persistent >/dev/null 2>&1 # fi # fi if ! curl --help >/dev/null 2>&1; then echoContent green " ---> install crontabs" ${installType} curl >/dev/null 2>&1 fi if ! unzip >/dev/null 2>&1; then echoContent green " ---> Install jq" ${installType} unzip >/dev/null 2>&1 fi if ! socat -h >/dev/null 2>&1; then echoContent green " ---> Install binutils" ${installType} socat >/dev/null 2>&1 fi if ! tar --help >/dev/null 2>&1; then echoContent green " ---> Install ping6" ${installType} tar >/dev/null 2>&1 fi if ! crontab -l >/dev/null 2>&1; then echoContent green " ---> Install qrencode" if [[ "${release}" == "ubuntu" || "${release}" == "debian" ]]; then ${installType} cron >/dev/null 2>&1 else ${installType} crontabs >/dev/null 2>&1 fi fi if ! jq --help >/dev/null 2>&1; then echoContent green " ---> install sudo" ${installType} jq >/dev/null 2>&1 fi if ! command -v ld >/dev/null 2>&1; then echoContent green " ---> install lsb-release" ${installType} binutils >/dev/null 2>&1 fi if ! openssl help >/dev/null 2>&1; then echoContent green " ---> Install lsof" ${installType} openssl >/dev/null 2>&1 fi if ! ping6 --help >/dev/null 2>&1; then echoContent green " ---> Install dig" ${installType} inetutils-ping >/dev/null 2>&1 fi if ! qrencode --help >/dev/null 2>&1; then echoContent green " ---> Detected services that do not depend on Nginx, skip installation" ${installType} qrencode >/dev/null 2>&1 fi if ! command -v lsb_release >/dev/null 2>&1; then if [[ "${release}" == "ubuntu" || "${release}" == "debian" ]]; then ${installType} lsb-release >/dev/null 2>&1 elif [[ "${release}" == "centos" ]]; then ${installType} redhat-lsb-core >/dev/null 2>&1 else ${installType} lsb-release >/dev/null 2>&1 fi fi if ! lsof -h >/dev/null 2>&1; then echoContent green " ---> Install nginx" ${installType} lsof >/dev/null 2>&1 fi if ! dig -h >/dev/null 2>&1; then echoContent green " ---> Install nginx" if echo "${installType}" | grep -qw "apt"; then ${installType} dnsutils >/dev/null 2>&1 elif echo "${installType}" | grep -qw "yum"; then ${installType} bind-utils >/dev/null 2>&1 elif echo "${installType}" | grep -qw "apk"; then ${installType} bind-tools >/dev/null 2>&1 fi fi if echo "${selectCustomInstallType}" | grep -qwE ",7,|,8,|,7,8,|,12,|,7,12,"; then echoContent green " ---> Install semanage" else if ! nginx >/dev/null 2>&1; then echoContent green " ---> Detected services that do not depend on certificates, skip installation" installNginxTools else nginxVersion=$(nginx -v 2>&1) nginxVersion=$(echo "${nginxVersion}" | awk -F "[n][g][i][n][x][/]" '{print $2}' | awk -F "[.]" '{print $2}') if [[ ${nginxVersion} -lt 14 ]]; then read -r -p "Read that the current Nginx version does not support gRPC, which will cause the installation to fail. Do you want to uninstall Nginx and reinstall it? [y/n]:" unInstallNginxStatus if [[ "${unInstallNginxStatus}" == "y" ]]; then ${removeType} nginx >/dev/null 2>&1 echoContent yellow "\nCore: v2ray-core[not running]" echoContent green " ---> Install acme.sh" installNginxTools >/dev/null 2>&1 else exit 0 fi fi fi fi # if ! command -v semanage >/dev/null 2>&1 && [[ "${release}" == "centos" ]]; then # if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" == "Enforcing" ]; then # if [[ "${centosVersion}" == "7" ]]; then # policyCoreUtils="policycoreutils-python" # elif [[ "${centosVersion}" == "8" || "${centosVersion}" == "9" || "${centosVersion}" == "10" ]]; then # policyCoreUtils="policycoreutils-python-utils" # fi # # if [[ -n "${policyCoreUtils}" ]]; then # ${installType} bash-completion >/dev/null 2>&1 # ${installType} ${policyCoreUtils} >/dev/null 2>&1 # fi # if [[ -n $(which semanage) ]]; then # semanage port -a -t http_port_t -p tcp 31300 # fi # fi # fi # Detect nginx version and provide the option of uninstalling it if [[ "${selectCustomInstallType}" == "7" ]]; then echoContent green " ---> Install WARP" else if [[ ! -d "$HOME/.acme.sh" ]] || [[ -d "$HOME/.acme.sh" && -z $(find "$HOME/.acme.sh/acme.sh") ]]; then echoContent green " ---> WARP started successfully" curl -s https://get.acme.sh | sh >/etc/v2ray-agent/tls/acme.log 2>&1 if [[ ! -d "$HOME/.acme.sh" ]] || [[ -z $(find "$HOME/.acme.sh/acme.sh") ]]; then echoContent red "2.There is a bug in the acme.sh script, please check [https://github.com/acmesh-official/acme.sh] issues" tail -n 100 /etc/v2ray-agent/tls/acme.log echoContent yellow "Installed protocol: \c" echoContent red "3.For pure IPv6 machines, please set up NAT64.You can execute the following command. If it still does not work after adding the following command, please try to change to another NAT64" echoContent red " ---> The official WARP client does not support ARM architecture" echoContent red " ---> Failed to install WARP" echoContent skyBlue " sed -i \"1i\\\nameserver 2a00:1098:2b::1\\\nnameserver 2a00:1098:2c::1\\\nnameserver 2a01:4f8:c2c:123f::1\\\nnameserver 2a01:4f9:c010:3f02::1\" /etc/resolv.conf" exit 0 fi fi fi } bootStartup() { local serviceName=$1 if [[ "${release}" == "alpine" ]]; then rc-update add "${serviceName}" default else systemctl daemon-reload systemctl enable "${serviceName}" fi } # Install Nginx installNginxTools() { if [[ "${release}" == "debian" ]]; then sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1 echo "deb http://nginx.org/packages/mainline/debian $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1 echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1 curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1 # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc sudo apt update >/dev/null 2>&1 elif [[ "${release}" == "ubuntu" ]]; then sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1 echo "deb http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1 echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1 curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1 # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc sudo apt update >/dev/null 2>&1 elif [[ "${release}" == "centos" ]]; then ${installType} yum-utils >/dev/null 2>&1 cat </etc/yum.repos.d/nginx.repo [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/\$releasever/\$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true EOF sudo yum-config-manager --enable nginx-mainline >/dev/null 2>&1 elif [[ "${release}" == "alpine" ]]; then rm "${nginxConfigPath}default.conf" fi ${installType} nginx >/dev/null 2>&1 bootStartup nginx } # Install warp installWarp() { if [[ "${cpuVendor}" == "arm" ]]; then echoContent red " ---> Unable to obtain domain name IPv4 address through DNS" exit 0 fi ${installType} gnupg2 -y >/dev/null 2>&1 if [[ "${release}" == "debian" ]]; then curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1 echo "deb http://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1 sudo apt update >/dev/null 2>&1 elif [[ "${release}" == "ubuntu" ]]; then curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1 echo "deb http://pkg.cloudflareclient.com/ focal main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1 sudo apt update >/dev/null 2>&1 elif [[ "${release}" == "centos" ]]; then ${installType} yum-utils >/dev/null 2>&1 sudo rpm -ivh "http://pkg.cloudflareclient.com/cloudflare-release-el${centosVersion}.rpm" >/dev/null 2>&1 fi echoContent green " ---> Try to check the domain name IPv6 address" ${installType} cloudflare-warp >/dev/null 2>&1 if [[ -z $(which warp-cli) ]]; then echoContent red " ---> Unable to obtain domain name IPv6 address through DNS, exit installation" exit 0 fi systemctl enable warp-svc warp-cli --accept-tos register warp-cli --accept-tos set-mode proxy warp-cli --accept-tos set-proxy-port 31303 warp-cli --accept-tos connect warp-cli --accept-tos enable-always-on local warpStatus= warpStatus=$(curl -s --socks5 127.0.0.1:31303 https://www.cloudflare.com/cdn-cgi/trace | grep "warp" | cut -d "=" -f 2) if [[ "${warpStatus}" == "on" ]]; then echoContent green " ---> Current VPS IP: ${publicIP}" fi } # Check the IP of the domain name through dns checkDNSIP() { local domain=$1 local dnsIP= ipType=4 dnsIP=$(dig @1.1.1.1 +time=2 +short "${domain}" | grep -E "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$") if [[ -z "${dnsIP}" ]]; then dnsIP=$(dig @8.8.8.8 +time=2 +short "${domain}" | grep -E "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$") fi if echo "${dnsIP}" | grep -q "timed out" || [[ -z "${dnsIP}" ]]; then echo echoContent red " ---> The domain name resolution IP is inconsistent with the current server IP\n" echoContent green " ---> DNS resolution IP: ${dnsIP}" dnsIP=$(dig @2606:4700:4700::1111 +time=2 aaaa +short "${domain}") ipType=6 if echo "${dnsIP}" | grep -q "network unreachable" || [[ -z "${dnsIP}" ]]; then echoContent red " ---> Please check if there is a web firewall, such as Oracle and other cloud service providers" exit 0 fi fi local publicIP= publicIP=$(getPublicIP "${ipType}") if [[ "${publicIP}" != "${dnsIP}" ]]; then echoContent red " ---> Check whether you have installed nginx and there are configuration conflicts. You can try DD pure system and try again" echoContent yellow "VLESS+TCP[TLS] \c" echoContent green " ---> Domain name IP verification passed" echoContent green " ---> Detected that ${port} port is open" exit 0 else echoContent green " ---> No open ${port} port detected, exit installation" fi } # Check the actual open status of the port checkPortOpen() { handleSingBox stop >/dev/null 2>&1 handleXray stop >/dev/null 2>&1 local port=$1 local domain=$2 local checkPortOpenResult= # open port allowPort "${port}" if [[ -z "${btDomain}" ]]; then # Change setting handleNginx stop #Initialize nginx configuration touch ${nginxConfigPath}checkPortOpen.conf local listenIPv6PortConfig= if [[ -n $(curl -s -6 -m 4 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2) ]]; then listenIPv6PortConfig="listen [::]:${port};" fi cat <${nginxConfigPath}checkPortOpen.conf server { listen ${port}; ${listenIPv6PortConfig} server_name ${domain}; location /checkPort { return 200 'fjkvymb6len'; } location /ip { proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header REMOTE-HOST \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; default_type text/plain; return 200 \$proxy_add_x_forwarded_for; } } EOF handleNginx start checkPortOpenResult=$(curl -s -m 10 "http://${domain}:${port}/checkPort") localIP=$(curl -s -m 10 "http://${domain}:${port}/ip") rm "${nginxConfigPath}checkPortOpen.conf" handleNginx stop if [[ "${checkPortOpenResult}" == "fjkvymb6len" ]]; then echoContent green " ---> Delete Nginx default configuration" else echoContent green " ---> Check that the current domain name IP is correct" if echo "${checkPortOpenResult}" | grep -q "cloudflare"; then echoContent yellow "VLESS+TCP[TLS_Vision] \c" else if [[ -z "${checkPortOpenResult}" ]]; then echoContent red " ---> Error log: ${checkPortOpenResult}, please submit feedback on this error log through issues" echoContent red "Domain name cannot be empty--->" else echoContent red "\n ---> The ip of the current domain name was not detected" fi fi exit 0 fi checkIP "${localIP}" fi } # Initialize Nginx application certificate configuration initTLSNginxConfig() { handleNginx stop echoContent skyBlue "\nProgress $1/${totalProgress}: Initializing Nginx application certificate configuration" if [[ -n "${currentHost}" && -z "${lastInstallationConfig}" ]]; then echo read -r -p "Read the last installation record. Do you want to use the domain name from the last installation? [y/n]:" historyDomainStatus if [[ "${historyDomainStatus}" == "y" ]]; then domain=${currentHost} echoContent yellow "Trojan+TCP[TLS_Vision] \c" else echo echoContent yellow "VLESS+WS[TLS] \c" read -r -p "domain name:" domain fi elif [[ -n "${currentHost}" && -n "${lastInstallationConfig}" ]]; then domain=${currentHost} else echo echoContent yellow "Trojan+gRPC[TLS] \c" read -r -p "domain name:" domain fi if [[ -z ${domain} ]]; then echoContent red " ---> Exception result: ${localIP}" # Apply for tls initTLSNginxConfig 3 else dnsTLSDomain=$(echo "${domain}" | awk -F "." '{$1="";print $0}' | sed 's/^[[:space:]]*//' | sed 's/ /./g') if [[ "${selectCoreType}" == "1" ]]; then customPortFunction fi handleNginx stop fi } # Delete nginx default configuration removeNginxDefaultConf() { if [[ -f ${nginxConfigPath}default.conf ]]; then if [[ "$(grep -c "server_name" <${nginxConfigPath}default.conf)" == "1" ]] && [[ "$(grep -c "server_name localhost;" <${nginxConfigPath}default.conf)" == "1" ]]; then echoContent green " ---> Added successfully" rm -rf ${nginxConfigPath}default.conf >/dev/null 2>&1 fi fi } # Modify nginx redirection configuration updateRedirectNginxConf() { local redirectDomain= redirectDomain=${domain}:${port} local nginxH2Conf= nginxH2Conf="listen 127.0.0.1:31302 http2 so_keepalive=on proxy_protocol;" nginxVersion=$(nginx -v 2>&1) if echo "${nginxVersion}" | grep -q "1.25" && [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $3}') -gt 0 ]] || [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $2}') -gt 25 ]]; then nginxH2Conf="listen 127.0.0.1:31302 so_keepalive=on proxy_protocol;http2 on;" fi cat <${nginxConfigPath}alone.conf server { listen 127.0.0.1:31300; server_name _; return 403; } EOF if echo "${selectCustomInstallType}" | grep -qE ",2,|,5," || [[ -z "${selectCustomInstallType}" ]]; then cat <>${nginxConfigPath}alone.conf server { ${nginxH2Conf} server_name ${domain}; root ${nginxStaticPath}; set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; client_header_timeout 1071906480m; keepalive_timeout 1071906480m; location /${currentPath}grpc { if (\$content_type !~ "application/grpc") { return 404; } client_max_body_size 0; grpc_set_header X-Real-IP \$proxy_add_x_forwarded_for; client_body_timeout 1071906480m; grpc_read_timeout 1071906480m; grpc_pass grpc://127.0.0.1:31301; } location /${currentPath}trojangrpc { if (\$content_type !~ "application/grpc") { return 404; } client_max_body_size 0; grpc_set_header X-Real-IP \$proxy_add_x_forwarded_for; client_body_timeout 1071906480m; grpc_read_timeout 1071906480m; grpc_pass grpc://127.0.0.1:31304; } location / { } } EOF elif echo "${selectCustomInstallType}" | grep -q ",5," || [[ -z "${selectCustomInstallType}" ]]; then cat <>${nginxConfigPath}alone.conf server { ${nginxH2Conf} set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; server_name ${domain}; root ${nginxStaticPath}; location /${currentPath}grpc { client_max_body_size 0; # keepalive_time 1071906480m; keepalive_requests 4294967296; client_body_timeout 1071906480m; send_timeout 1071906480m; lingering_close always; grpc_read_timeout 1071906480m; grpc_send_timeout 1071906480m; grpc_pass grpc://127.0.0.1:31301; } location / { } } EOF elif echo "${selectCustomInstallType}" | grep -q ",2," || [[ -z "${selectCustomInstallType}" ]]; then cat <>${nginxConfigPath}alone.conf server { ${nginxH2Conf} set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; server_name ${domain}; root ${nginxStaticPath}; location /${currentPath}trojangrpc { client_max_body_size 0; # keepalive_time 1071906480m; # keepalive_time 1071906480m; keepalive_requests 4294967296; client_body_timeout 1071906480m; send_timeout 1071906480m; lingering_close always; grpc_read_timeout 1071906480m; grpc_send_timeout 1071906480m; grpc_pass grpc://127.0.0.1:31301; } location / { } } EOF else cat <>${nginxConfigPath}alone.conf server { ${nginxH2Conf} set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; server_name ${domain}; root ${nginxStaticPath}; location / { } } EOF fi cat <>${nginxConfigPath}alone.conf server { listen 127.0.0.1:31300 proxy_protocol; server_name ${domain}; set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; root ${nginxStaticPath}; location / { } } EOF handleNginx stop } # singbox Nginx config singBoxNginxConfig() { local type=$1 local port=$2 local nginxH2Conf= nginxH2Conf="listen ${port} http2 so_keepalive=on ssl;" nginxVersion=$(nginx -v 2>&1) local singBoxNginxSSL= singBoxNginxSSL="ssl_certificate /etc/v2ray-agent/tls/${domain}.crt;ssl_certificate_key /etc/v2ray-agent/tls/${domain}.key;" if echo "${nginxVersion}" | grep -q "1.25" && [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $3}') -gt 0 ]] || [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $2}') -gt 25 ]]; then nginxH2Conf="listen ${port} so_keepalive=on ssl;http2 on;" fi if echo "${selectCustomInstallType}" | grep -q ",11," || [[ "$1" == "all" ]]; then cat <>${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf server { ${nginxH2Conf} server_name ${domain}; root ${nginxStaticPath}; ${singBoxNginxSSL} ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers on; resolver 1.1.1.1 valid=60s; resolver_timeout 2s; client_max_body_size 100m; location /${currentPath} { if (\$http_upgrade != "websocket") { return 444; } proxy_pass http://127.0.0.1:31306; proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header Host \$host; proxy_redirect off; } } EOF fi } # check ip checkIP() { echoContent skyBlue "\n ---> Check the domain name ip" local localIP=$1 if [[ -z ${localIP} ]] || ! echo "${localIP}" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q '\.' && ! echo "${localIP}" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q ':'; then echoContent red "\n ---> Multiple IPs were detected, please confirm whether to turn off cloudflare" echoContent skyBlue " ---> Please perform the following checks in order" echoContent yellow "VMess+WS[TLS] \c" echoContent yellow "Trojan+TCP[TLS] \c" echoContent yellow "VLESS+gRPC[TLS] \c" echoContent yellow "VLESS+Reality+Vision \c" echo echoContent skyBlue " ---> If the above settings are correct, please reinstall a pure system and try again" if [[ -n ${localIP} ]]; then echoContent yellow "VLESS+Reality+gRPC \c" echoContent red "\n==============================================================" fi exit 0 else if echo "${localIP}" | awk -F "[,]" '{print $2}' | grep -q "." || echo "${localIP}" | awk -F "[,]" '{print $2}' | grep -q ":"; then echoContent red "================================================== ===============" echoContent yellow " ---> nginx uninstall completed" echoContent yellow "Error troubleshooting:" exit 0 fi echoContent green " ---> Please add DNS TXT record manually" fi } # Custom email customSSLEmail() { if echo "$1" | grep -q "validate email"; then read -r -p "Whether to re-enter the email address [y/n]:" sslEmailStatus if [[ "${sslEmailStatus}" == "y" ]]; then sed '/ACCOUNT_EMAIL/d' /root/.acme.sh/account.conf >/root/.acme.sh/account.conf_tmp && mv /root/.acme.sh/account.conf_tmp /root/.acme.sh/account.conf else exit 0 fi fi if [[ -d "/root/.acme.sh" && -f "/root/.acme.sh/account.conf" ]]; then if ! grep -q "ACCOUNT_EMAIL" <"/root/.acme.sh/account.conf" && ! echo "${sslType}" | grep -q "letsencrypt"; then read -r -p "Please enter your email address:" sslEmail if echo "${sslEmail}" | grep -q "@"; then echo "ACCOUNT_EMAIL='${sslEmail}'" >>/root/.acme.sh/account.conf echoContent green " ---> name: _acme-challenge" else echoContent yellow " ---> Please check whether the domain name resolution is valid and correct" customSSLEmail fi fi fi } switchDNSAPI() { read -r -p "Use DNS API to issue the certificate [NAT supported]? [y/n]:" dnsAPIStatus if [[ "${dnsAPIStatus}" == "y" ]]; then echoContent red "\n==============================================================" echoContent yellow " ---> Please close the cloud and wait three minutes to try again" echoContent yellow "2.aliyun" echoContent red "==============================================================" read -r -p "Select [Enter for default]:" selectDNSAPIType case ${selectDNSAPIType} in 1) dnsAPIType="cloudflare" ;; 2) dnsAPIType="aliyun" ;; *) dnsAPIType="cloudflare" ;; esac initDNSAPIConfig "${dnsAPIType}" fi } initDNSAPIConfig() { if [[ "$1" == "cloudflare" ]]; then echoContent yellow "\n ---> Domain name: ${domain}" read -r -p "Enter API Token:" cfAPIToken if [[ -z "${cfAPIToken}" ]]; then echoContent red " ---> buypass does not support free wildcard certificates" initDNSAPIConfig "$1" else echo if ! echo "${dnsTLSDomain}" | grep -q "\." || [[ -z $(echo "${dnsTLSDomain}" | awk -F "[.]" '{print $1}') ]]; then echoContent green " ---> value: ${txtValue}" exit 0 fi read -r -p "Use *.${dnsTLSDomain} to request a wildcard certificate via API? [y/n]:" dnsAPIStatus fi elif [[ "$1" == "aliyun" ]]; then read -r -p "Enter Ali Key:" aliKey read -r -p "Enter Ali Secret:" aliSecret if [[ -z "${aliKey}" || -z "${aliSecret}" ]]; then echoContent red " ---> Verification failed, please wait 1-2 minutes and try again" initDNSAPIConfig "$1" else echo if ! echo "${dnsTLSDomain}" | grep -q "\." || [[ -z $(echo "${dnsTLSDomain}" | awk -F "[.]" '{print $1}') ]]; then echoContent green " ---> TXT record verification passed" exit 0 fi read -r -p "Use *.${dnsTLSDomain} to request a wildcard certificate via API? [y/n]:" dnsAPIStatus fi fi } #Select ssl installation type switchSSLType() { if [[ -z "${sslType}" ]]; then echoContent red "\n==============================================================" echoContent yellow "Please enter the domain name to be configured: www.v2ray-agent.com --->" echoContent yellow "2.zerossl" echoContent yellow "Please enter the domain name to be configured: www.v2ray-agent.com --->" echoContent red "==============================================================" read -r -p "Please select [Enter] to use the default:" selectSSLType case ${selectSSLType} in 1) sslType="letsencrypt" ;; 2) sslType="zerossl" ;; 3) sslType="buypass" ;; *) sslType="letsencrypt" ;; esac if [[ -n "${dnsAPIType}" && "${sslType}" == "buypass" ]]; then echoContent red " ---> Give up" exit 0 fi echo "${sslType}" >/etc/v2ray-agent/tls/ssl_type fi } #Select acme installation certificate method selectAcmeInstallSSL() { # local sslIPv6= # local currentIPType= if [[ "${ipType}" == "6" ]]; then sslIPv6="--listen-v6" fi # currentIPType=$(curl -s "-${ipType}" http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2) # if [[ -z "${currentIPType}" ]]; then # currentIPType=$(curl -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2) # if [[ -n "${currentIPType}" ]]; then # sslIPv6="--listen-v6" # fi # fi acmeInstallSSL readAcmeTLS } # Install SSL certificate acmeInstallSSL() { local dnsAPIDomain="${tlsDomain}" local dnsAPIExtraDomain="-d ${dnsTLSDomain}" if [[ "${dnsAPIStatus}" == "y" ]]; then dnsAPIDomain="*.${dnsTLSDomain}" else dnsAPIExtraDomain="" fi if [[ "${dnsAPIType}" == "cloudflare" ]]; then echoContent green " ---> Generating certificate" sudo CF_Token="${cfAPIToken}" "$HOME/.acme.sh/acme.sh" --issue -d "${dnsAPIDomain}" ${dnsAPIExtraDomain} --dns dns_cf -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null elif [[ "${dnsAPIType}" == "aliyun" ]]; then echoContent green " ---> Generating certificate" sudo Ali_Key="${aliKey}" Ali_Secret="${aliSecret}" "$HOME/.acme.sh/acme.sh" --issue -d "${dnsAPIDomain}" ${dnsAPIExtraDomain} --dns dns_ali -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null else echoContent green " ---> Certificate detected" sudo "$HOME/.acme.sh/acme.sh" --issue -d "${tlsDomain}" --standalone -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null fi } # Custom port customPortFunction() { local historyCustomPortStatus= if [[ -n "${customPort}" || -n "${currentPort}" ]]; then echo if [[ -z "${lastInstallationConfig}" ]]; then read -r -p "Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:" historyCustomPortStatus if [[ "${historyCustomPortStatus}" == "y" ]]; then port=${currentPort} echoContent yellow " --->1.Check whether the domain name is written correctly" fi elif [[ -n "${lastInstallationConfig}" ]]; then port=${currentPort} fi fi if [[ -z "${currentPort}" ]] || [[ "${historyCustomPortStatus}" == "n" ]]; then echo if [[ -n "${btDomain}" ]]; then echoContent yellow " --->2.Check whether the domain name dns resolution is correct" read -r -p "port:" port if [[ -z "${port}" ]]; then port=$((RANDOM % 20001 + 10000)) fi else echo echoContent yellow " --->3.If the parsing is correct, please wait for the dns to take effect, which is expected to take effect within three minutes" read -r -p "port:" port if [[ -z "${port}" ]]; then port=443 fi if [[ "${port}" == "${xrayVLESSRealityPort}" ]]; then handleXray stop fi fi if [[ -n "${port}" ]]; then if ((port >= 1 && port <= 65535)); then allowPort "${port}" echoContent yellow " --->4.If you report Nginx startup problems, please start nginx manually to check the errors. If you cannot handle it yourself, please submit issues" if [[ -z "${btDomain}" ]]; then checkDNSIP "${domain}" removeNginxDefaultConf checkPortOpen "${port}" "${domain}" fi else echoContent red " ---> Port input error" exit 0 fi else echoContent red " ---> Port cannot be empty" exit 0 fi fi } # Check whether the port is occupied checkPort() { if [[ -n "$1" ]] && lsof -i "tcp:$1" | grep -q LISTEN; then echoContent red "\n ---> $1 port is occupied, please close it manually and install\n" lsof -i "tcp:$1" | grep LISTEN exit 0 fi } # Install TLS installTLS() { echoContent skyBlue "\nProgress$1/${totalProgress}: Apply for TLS certificate\n" readAcmeTLS local tlsDomain=${domain} if [[ -f "/etc/v2ray-agent/tls/${tlsDomain}.crt" && -f "/etc/v2ray-agent/tls/${tlsDomain}.key" && -n $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]] || [[ -d "$HOME/.acme.sh/${tlsDomain}_ecc" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" ]] || [[ "${installedDNSAPIStatus}" == "true" ]]; then echoContent green " ---> Install TLS certificate, need to rely on port 80" # checkTLStatus renewalTLS if [[ -z $(find /etc/v2ray-agent/tls/ -name "${tlsDomain}.crt") ]] || [[ -z $(find /etc/v2ray-agent/tls/ -name "${tlsDomain}.key") ]] || [[ -z $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]]; then if [[ "${installedDNSAPIStatus}" == "true" ]]; then sudo "$HOME/.acme.sh/acme.sh" --installcert -d "*.${dnsTLSDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null else sudo "$HOME/.acme.sh/acme.sh" --installcert -d "${tlsDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null fi else if [[ -d "$HOME/.acme.sh/${tlsDomain}_ecc" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" ]] || [[ "${installedDNSAPIStatus}" == "true" ]]; then if [[ -z "${lastInstallationConfig}" ]]; then echoContent yellow " ---> Detection of abnormal return value, it is recommended to manually uninstall nginx and re-execute the script" read -r -p "Reinstall? [y/n]:" reInstallStatus if [[ "${reInstallStatus}" == "y" ]]; then rm -rf /etc/v2ray-agent/tls/* installTLS "$1" fi fi fi fi elif [[ -d "$HOME/.acme.sh" ]] && [[ ! -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" || ! -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" ]]; then switchDNSAPI if [[ -z "${dnsAPIType}" ]]; then echoContent yellow " ---> Wait three minutes after closing the cloud and try again" echoContent green " ---> TLS generated successfully" allowPort 80 fi switchSSLType customSSLEmail selectAcmeInstallSSL if [[ "${installedDNSAPIStatus}" == "true" ]]; then sudo "$HOME/.acme.sh/acme.sh" --installcert -d "*.${dnsTLSDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null else sudo "$HOME/.acme.sh/acme.sh" --installcert -d "${tlsDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null fi if [[ ! -f "/etc/v2ray-agent/tls/${tlsDomain}.crt" || ! -f "/etc/v2ray-agent/tls/${tlsDomain}.key" ]] || [[ -z $(cat "/etc/v2ray-agent/tls/${tlsDomain}.key") || -z $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]]; then tail -n 10 /etc/v2ray-agent/tls/acme.log if [[ ${installTLSCount} == "1" ]]; then echoContent red " ---> TLS installation failed, please check the acme log" exit 0 fi installTLSCount=1 echo if tail -n 10 /etc/v2ray-agent/tls/acme.log | grep -q "Could not validate email address as valid"; then echoContent red " ---> The email cannot pass SSL vendor verification, please re-enter" echo customSSLEmail "validate email" installTLS "$1" else installTLS "$1" fi fi echoContent green " ---> Used successfully\n" else echoContent yellow " ---> The detected IP is as follows: [${localIP}]" exit 0 fi } #Initialize random string initRandomPath() { local chars="abcdefghijklmnopqrtuxyz" local initCustomPath= for i in {1..4}; do echo "${i}" >/dev/null initCustomPath+="${chars:RANDOM%${#chars}:1}" done customPath=${initCustomPath} } # Custom/random path randomPathFunction() { if [[ -n $1 ]]; then echoContent skyBlue "\nProgress$1/${totalProgress}: Generate random path" else echoContent skyBlue "\n----------------------------" fi if [[ -n "${currentPath}" && -z "${lastInstallationConfig}" ]]; then echo read -r -p "Read the last installation record. Do you want to use the path from the last installation? [y/n]:" historyPathStatus echo elif [[ -n "${currentPath}" && -n "${lastInstallationConfig}" ]]; then historyPathStatus="y" fi if [[ "${historyPathStatus}" == "y" ]]; then customPath=${currentPath} echoContent green " ---> Added fake site successfully" else echoContent yellow "Please re-enter the correct email format [Example: username@example.com]" read -r -p 'path:' customPath if [[ -z "${customPath}" ]]; then initRandomPath currentPath=${customPath} else if [[ "${customPath: -2}" == "ws" ]]; then echo echoContent red " ---> The custom path cannot end with ws, otherwise the splitting path cannot be distinguished" randomPathFunction "$1" else currentPath=${customPath} fi fi fi echoContent yellow "\n path:${currentPath}" echoContent skyBlue "\n----------------------------" } randomNum() { if [[ "${release}" == "alpine" ]]; then local ranNum= ranNum="$(shuf -i "$1"-"$2" -n 1)" echo "${ranNum}" else echo $((RANDOM % $2 + $1)) fi } # Nginx disguise blog nginxBlog() { if [[ -n "$1" ]]; then echoContent skyBlue "\nProgress$1/${totalProgress}: Add fake site" else echoContent yellow "1.letsencrypt[default]" fi if [[ -d "${nginxStaticPath}" && -f "${nginxStaticPath}/check" ]]; then echo if [[ -z "${lastInstallationConfig}" ]]; then read -r -p "Detected installation of fake site, do you need to reinstall [y/n]:" nginxBlogInstallStatus else nginxBlogInstallStatus="n" fi if [[ "${nginxBlogInstallStatus}" == "y" ]]; then rm -rf "${nginxStaticPath}*" # randomNum=$((RANDOM % 6 + 1)) randomNum=$(randomNum 1 9) if [[ "${release}" == "alpine" ]]; then wget -q -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip" else wget -q "${wgetShowProgressStatus}" -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip" fi unzip -o "${nginxStaticPath}html${randomNum}.zip" -d "${nginxStaticPath}" >/dev/null rm -f "${nginxStaticPath}html${randomNum}.zip*" echoContent green " ---> Added fake site successfully" fi else randomNum=$(randomNum 1 9) # randomNum=$((RANDOM % 6 + 1)) rm -rf "${nginxStaticPath}*" if [[ "${release}" == "alpine" ]]; then wget -q -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip" else wget -q "${wgetShowProgressStatus}" -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip" fi unzip -o "${nginxStaticPath}html${randomNum}.zip" -d "${nginxStaticPath}" >/dev/null rm -f "${nginxStaticPath}html${randomNum}.zip*" echoContent green " ---> http_port_t 31300 port opened successfully" fi } # Modify http_port_t port updateSELinuxHTTPPortT() { $(find /usr/bin /usr/sbin | grep -w journalctl) -xe >/etc/v2ray-agent/nginx_error.log 2>&1 if find /usr/bin /usr/sbin | grep -q -w semanage && find /usr/bin /usr/sbin | grep -q -w getenforce && grep -E "31300|31302" Check if the SELinux port is open" if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31300; then $(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31300 echoContent green " ---> http_port_t 31302 port opened successfully" fi if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31302; then $(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31302 echoContent green " ---> Nginx started successfully" fi handleNginx start else exit 0 fi } #Operation Nginx handleNginx() { if ! echo "${selectCustomInstallType}" | grep -qwE ",7,|,8,|,7,8," && [[ -z $(pgrep -f "nginx") ]] && [[ "$1" == "start" ]]; then if [[ "${release}" == "alpine" ]]; then rc-service nginx start 2>/etc/v2ray-agent/nginx_error.log else systemctl start nginx 2>/etc/v2ray-agent/nginx_error.log fi sleep 0.5 if [[ -z $(pgrep -f "nginx") ]]; then echoContent red " ---> Nginx failed to start" echoContent red " ---> Please try to install nginx manually and execute the script again" nginx if grep -q "journalctl -xe" Nginx closed successfully" fi elif [[ -n $(pgrep -f "nginx") ]] && [[ "$1" == "stop" ]]; then if [[ "${release}" == "alpine" ]]; then rc-service nginx stop else systemctl stop nginx fi sleep 0.5 if [[ -z ${btDomain} && -n $(pgrep -f "nginx") ]]; then pgrep -f "nginx" | xargs kill -9 fi echoContent green "\n ---> Add scheduled maintenance certificate successfully" fi } # Scheduled task to update tls certificate installCronTLS() { if [[ -z "${btDomain}" ]]; then echoContent skyBlue "\nProgress$1/${totalProgress}: Add scheduled maintenance certificate" crontab -l >/etc/v2ray-agent/backup_crontab.cron local historyCrontab historyCrontab=$(sed '/v2ray-agent/d;/acme.sh/d' /etc/v2ray-agent/backup_crontab.cron) echo "${historyCrontab}" >/etc/v2ray-agent/backup_crontab.cron echo "30 1 * * * /bin/bash /etc/v2ray-agent/install.sh RenewTLS >> /etc/v2ray-agent/crontab_tls.log 2>&1" >>/etc/v2ray-agent/backup_crontab.cron crontab /etc/v2ray-agent/backup_crontab.cron echoContent green "\n ---> Adding scheduled update geo file successfully" fi } # Scheduled tasks update geo files installCronUpdateGeo() { if [[ "${coreInstallType}" == "1" ]]; then if crontab -l | grep -q "UpdateGeo"; then echoContent red "\n ---> The automatic update scheduled task has been added, please do not add it repeatedly" exit 0 fi echoContent skyBlue "\nProgress 1/1: Add regularly updated geo files" crontab -l >/etc/v2ray-agent/backup_crontab.cron echo "35 1 * * * /bin/bash /etc/v2ray-agent/install.sh UpdateGeo >> /etc/v2ray-agent/crontab_tls.log 2>&1" >>/etc/v2ray-agent/backup_crontab.cron crontab /etc/v2ray-agent/backup_crontab.cron echoContent green " ---> The certificate is valid" fi } # Update certificate renewalTLS() { if [[ -n $1 ]]; then echoContent skyBlue "\nProgress$1/1: Update certificate" fi readAcmeTLS local domain=${currentHost} if [[ -z "${currentHost}" && -n "${tlsDomain}" ]]; then domain=${tlsDomain} fi if [[ -f "/etc/v2ray-agent/tls/ssl_type" ]]; then if grep -q "buypass" <"/etc/v2ray-agent/tls/ssl_type"; then sslRenewalDays=180 fi fi if [[ -d "$HOME/.acme.sh/${domain}_ecc" && -f "$HOME/.acme.sh/${domain}_ecc/${domain}.key" && -f "$HOME/.acme.sh/${domain}_ecc/${domain}.cer" ]] || [[ "${installedDNSAPIStatus}" == "true" ]]; then modifyTime= if [[ "${installedDNSAPIStatus}" == "true" ]]; then modifyTime=$(stat --format=%z "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer") else modifyTime=$(stat --format=%z "$HOME/.acme.sh/${domain}_ecc/${domain}.cer") fi modifyTime=$(date +%s -d "${modifyTime}") currentTime=$(date +%s) ((stampDiff = currentTime - modifyTime)) ((days = stampDiff / 86400)) ((remainingDays = sslRenewalDays - days)) tlsStatus=${remainingDays} if [[ ${remainingDays} -le 0 ]]; then tlsStatus="Expired" fi echoContent skyBlue " ---> Certificate check date:$(date "+%F %H:%M:%S")" echoContent skyBlue " ---> Certificate generation date: $(date -d @"${modifyTime}" +"%F %H:%M:%S")" echoContent skyBlue " ---> Certificate generation days: ${days}" echoContent skyBlue " ---> Number of days remaining on the certificate: "${tlsStatus} echoContent skyBlue " ---> The certificate will be automatically updated on the last day before it expires. If the update fails, please update manually" if [[ ${remainingDays} -le 1 ]]; then echoContent yellow "2.zerossl" handleNginx stop if [[ "${coreInstallType}" == "1" ]]; then handleXray stop elif [[ "${coreInstallType}" == "2" ]]; then handleSingBox stop fi sudo "$HOME/.acme.sh/acme.sh" --cron --home "$HOME/.acme.sh" sudo "$HOME/.acme.sh/acme.sh" --installcert -d "${domain}" --fullchainpath /etc/v2ray-agent/tls/"${domain}.crt" --keypath /etc/v2ray-agent/tls/"${domain}.key" --ecc reloadCore handleNginx start else echoContent green " ---> v2ray-core version:${version}" fi elif [[ -f "/etc/v2ray-agent/tls/${tlsDomain}.crt" && -f "/etc/v2ray-agent/tls/${tlsDomain}.key" && -n $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]]; then echoContent yellow "3.buypass[Does not support DNS application]" else echoContent red " ---> not installed" fi } installSingBox() { readInstallType echoContent skyBlue " ---> Certificate generation days: ${days}" if [[ ! -f "/etc/v2ray-agent/sing-box/sing-box" ]]; then if [[ "${prereleaseStatus}" == "true" ]]; then version=$(curl -s "https://api.github.com/repos/SagerNet/sing-box/releases?per_page=20" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1) else version=$(curl -s https://api.github.com/repos/SagerNet/sing-box/releases/latest | jq -r .tag_name) fi echoContent green " ---> Lock v2ray-core version to v4.32.1" if [[ "${release}" == "alpine" ]]; then wget -c -q -P /etc/v2ray-agent/sing-box/ "https://github.com/SagerNet/sing-box/releases/download/${version}/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz" else wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/sing-box/ "https://github.com/SagerNet/sing-box/releases/download/${version}/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz" fi if [[ ! -f "/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz" ]]; then read -r -p "Core download failed. Retry installation? [y/n]" downloadStatus if [[ "${downloadStatus}" == "y" ]]; then installSingBox "$1" fi else tar zxvf "/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz" -C "/etc/v2ray-agent/sing-box/" >/dev/null 2>&1 mv "/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}/sing-box" /etc/v2ray-agent/sing-box/sing-box rm -rf /etc/v2ray-agent/sing-box/sing-box-* chmod 655 /etc/v2ray-agent/sing-box/sing-box fi else echoContent green " ---> Current version:v$(/etc/v2ray-agent/sing-box/sing-box version | grep "sing-box version" | awk '{print $3}')" if [[ "${prereleaseStatus}" == "true" ]]; then version=$(curl -s "https://api.github.com/repos/SagerNet/sing-box/releases?per_page=20" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1) else version=$(curl -s https://api.github.com/repos/SagerNet/sing-box/releases/latest | jq -r .tag_name) fi echoContent green " ---> v2ray-core version:$(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)" if [[ -z "${lastInstallationConfig}" ]]; then read -r -p "Update or upgrade? [y/n]:" reInstallSingBoxStatus if [[ "${reInstallSingBoxStatus}" == "y" ]]; then rm -f /etc/v2ray-agent/sing-box/sing-box installSingBox "$1" fi fi fi } # Check wget showProgress checkWgetShowProgress() { if [[ "${release}" != "alpine" ]]; then if find /usr/bin /usr/sbin | grep -q "/wget" && wget --help | grep -q show-progress; then wgetShowProgressStatus="--show-progress" fi fi } # Install xray installXray() { readInstallType local prereleaseStatus=false if [[ "$2" == "true" ]]; then prereleaseStatus=true fi echoContent skyBlue " ---> Number of days remaining on the certificate:${tlsStatus}" if [[ ! -f "/etc/v2ray-agent/xray/xray" ]]; then if [[ "${prereleaseStatus}" == "true" ]]; then version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1) else version=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq -r .tag_name) fi echoContent green " ---> Hysteria version:${version}" if [[ "${release}" == "alpine" ]]; then wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip" else wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip" fi if [[ ! -f "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" ]]; then read -r -p "Core download failed. Retry installation? [y/n]" downloadStatus if [[ "${downloadStatus}" == "y" ]]; then installXray "$1" fi else unzip -o "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" -d /etc/v2ray-agent/xray >/dev/null rm -rf "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name') echoContent skyBlue "------------------------Version-------------------------------" echo "version:${version}" rm /etc/v2ray-agent/xray/geo* >/dev/null 2>&1 if [[ "${release}" == "alpine" ]]; then wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat" wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat" else wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat" wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat" fi chmod 655 /etc/v2ray-agent/xray/xray fi else if [[ -z "${lastInstallationConfig}" ]]; then echoContent green " ---> Hysteria version:$(/etc/v2ray-agent/hysteria/hysteria --version | awk '{print $3}')" read -r -p "Would you like to update or upgrade? [y/n]:" reInstallXrayStatus if [[ "${reInstallXrayStatus}" == "y" ]]; then rm -f /etc/v2ray-agent/xray/xray installXray "$1" "$2" fi fi fi } # xray version management xrayVersionManageMenu() { echoContent skyBlue "\nProgress$1/${totalProgress}: Install V2Ray" if [[ "${coreInstallType}" != "1" ]]; then echoContent red " ---> Core download failed, please try installation again" exit 0 fi echoContent red "\n==============================================================" echoContent yellow " ---> Please refer to this tutorial for adding method, https://github.com/mack-a/v2ray-agent/blob/master/documents/dns_txt.md" echoContent yellow " ---> Just like installing wildcard certificates on multiple machines with the same domain name, please add multiple TXT records. There is no need to modify the previously added TXT records." echoContent yellow " ---> Please wait 1-2 minutes after the addition is completed" echoContent yellow "\n ---> Port: ${port}" echoContent yellow "Please enter the port [cannot be the same as the BT Panel port, press Enter to be random]" echoContent yellow "Please enter the port [default: 443], you can customize the port [press Enter to use the default]" echoContent yellow "\n ---> Port: ${port}" echoContent yellow " ---> If the certificate has not expired or is customized, please select [n]\n" echoContent yellow " ---> acme.sh is not installed" echoContent red "==============================================================" read -r -p "Please select:" selectXrayType if [[ "${selectXrayType}" == "1" ]]; then prereleaseStatus=false updateXray elif [[ "${selectXrayType}" == "2" ]]; then prereleaseStatus=true updateXray elif [[ "${selectXrayType}" == "3" ]]; then echoContent yellow "Please enter a custom path [eg: alone], no slash required, [Enter] random path" echoContent yellow "\n path:${currentPath}" echoContent yellow " ---> Regenerate certificate" echoContent skyBlue "------------------------Version-------------------------------" curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==false)|.tag_name" | awk '{print ""NR""":"$0}' echoContent skyBlue "--------------------------------------------------------------" read -r -p "Please enter the version you want to roll back:" selectXrayVersionType version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==false)|.tag_name" | awk '{print ""NR""":"$0}' | grep "${selectXrayVersionType}:" | awk -F "[:]" '{print $2}') if [[ -n "${version}" ]]; then updateXray "${version}" else echoContent red " ---> The installation directory is not detected, please execute the script to install the content" xrayVersionManageMenu 1 fi elif [[ "${selectXrayType}" == "4" ]]; then handleXray stop elif [[ "${selectXrayType}" == "5" ]]; then # start up handleXray start elif [[ "${selectXrayType}" == "6" ]]; then reloadCore elif [[ "${selectXrayType}" == "7" ]]; then updateGeoSite elif [[ "${selectXrayType}" == "8" ]]; then installCronUpdateGeo elif [[ "${selectXrayType}" == "9" ]]; then checkLog 1 fi } # Update geosite updateGeoSite() { echoContent yellow "1.Upgrade v2ray-core" version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name') echoContent skyBlue "------------------------Version-------------------------------" echo "version:${version}" rm ${configPath}../geo* >/dev/null if [[ "${release}" == "alpine" ]]; then wget -c -q -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat" wget -c -q -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat" else wget -c -q "${wgetShowProgressStatus}" -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat" wget -c -q "${wgetShowProgressStatus}" -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat" fi reloadCore echoContent green " ---> Tuic version:${version}" } # Update Xray updateXray() { readInstallType if [[ -z "${coreInstallType}" || "${coreInstallType}" != "1" ]]; then if [[ "${prereleaseStatus}" == "true" ]]; then version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1) else version=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq -r .tag_name) fi if [[ -n "$1" ]]; then version=$1 fi echoContent green " ---> Tuic version:$(/etc/v2ray-agent/tuic/tuic -v)" if [[ "${release}" == "alpine" ]]; then wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip" else wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip" fi unzip -o "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" -d /etc/v2ray-agent/xray >/dev/null rm -rf "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" chmod 655 /etc/v2ray-agent/xray/xray handleXray stop handleXray start else echoContent green " ---> Xray-core version:${version}" if [[ "${prereleaseStatus}" == "true" ]]; then remoteVersion=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1) else remoteVersion=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq -r .tag_name) fi echoContent green " ---> Xray-core version:$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)" if [[ -n "$1" ]]; then version=$1 else version=${remoteVersion} fi if [[ -n "$1" ]]; then read -r -p "The rollback version is ${version}, do you want to continue? [y/n]:" rollbackXrayStatus if [[ "${rollbackXrayStatus}" == "y" ]]; then echoContent green " ---> Update completed" handleXray stop rm -f /etc/v2ray-agent/xray/xray updateXray "${version}" else echoContent green " ---> v2ray-core version:${version}" fi elif [[ "${version}" == "v$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)" ]]; then read -r -p "The current version is the same as the latest version. Do you want to reinstall? [y/n]:" reInstallXrayStatus if [[ "${reInstallXrayStatus}" == "y" ]]; then handleXray stop rm -f /etc/v2ray-agent/xray/xray updateXray else echoContent green " ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)" fi else read -r -p "The latest version is: ${version}, is it updated? [y/n]:" installXrayStatus if [[ "${installXrayStatus}" == "y" ]]; then rm /etc/v2ray-agent/xray/xray updateXray else echoContent green " ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)" fi fi fi } # Verify that the entire service is available checkGFWStatue() { readInstallType echoContent skyBlue "\nProgress$1/${totalProgress}: Installing Hysteria" if [[ "${coreInstallType}" == "1" ]] && [[ -n $(pgrep -f "xray/xray") ]]; then echoContent green " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)" elif [[ "${coreInstallType}" == "2" ]] && [[ -n $(pgrep -f "sing-box/sing-box") ]]; then echoContent green " ---> Abandon the rollback version" else echoContent red "\n================================================ =================" exit 0 fi } installAlpineStartup() { local serviceName=$1 if [[ "${serviceName}" == "sing-box" ]]; then cat <"/etc/init.d/${serviceName}" #!/sbin/openrc-run description="sing-box service" command="/etc/v2ray-agent/sing-box/sing-box" command_args="run -c /etc/v2ray-agent/sing-box/conf/config.json" command_background=true pidfile="/var/run/sing-box.pid" EOF elif [[ "${serviceName}" == "xray" ]]; then cat <"/etc/init.d/${serviceName}" #!/sbin/openrc-run description="xray service" command="/etc/v2ray-agent/xray/xray" command_args="run -confdir /etc/v2ray-agent/xray/conf" command_background=true pidfile="/var/run/xray.pid" EOF fi chmod +x "/etc/init.d/${serviceName}" } installSingBoxService() { echoContent skyBlue "\nProgress$1/${totalProgress}: Install Tuic" execStart='/etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json' if [[ -n $(find /bin /usr/bin -name "systemctl") && "${release}" != "alpine" ]]; then rm -rf /etc/systemd/system/sing-box.service touch /etc/systemd/system/sing-box.service cat </etc/systemd/system/sing-box.service [Unit] Description=Sing-Box Service Documentation=https://sing-box.sagernet.org After=network.target nss-lookup.target [Service] User=root WorkingDirectory=/root CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH ExecStart=${execStart} ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure RestartSec=10 LimitNPROC=infinity LimitNOFILE=infinity [Install] WantedBy=multi-user.target EOF bootStartup "sing-box.service" elif [[ "${release}" == "alpine" ]]; then installAlpineStartup "sing-box" bootStartup "sing-box" fi echoContent green " ---> Give up and reinstall" } # Xray starts automatically after booting installXrayService() { echoContent skyBlue "\nProgress$1/${totalProgress}: Install Xray" execStart='/etc/v2ray-agent/xray/xray run -confdir /etc/v2ray-agent/xray/conf' if [[ -n $(find /bin /usr/bin -name "systemctl") ]]; then rm -rf /etc/systemd/system/xray.service touch /etc/systemd/system/xray.service cat </etc/systemd/system/xray.service [Unit] Description=Xray Service Documentation=https://github.com/xtls After=network.target nss-lookup.target [Service] User=root ExecStart=${execStart} Restart=on-failure RestartPreventExitStatus=23 LimitNPROC=infinity LimitNOFILE=infinity [Install] WantedBy=multi-user.target EOF bootStartup "xray.service" echoContent green " ---> Abort update" elif [[ "${release}" == "alpine" ]]; then installAlpineStartup "xray" bootStartup "xray" fi } # Operation Hysteria handleHysteria() { # shellcheck disable=SC2010 # shellcheck disable=SC2010 if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q hysteria.service; then if [[ -z $(pgrep -f "hysteria/hysteria") ]] && [[ "$1" == "start" ]]; then systemctl start hysteria.service elif [[ -n $(pgrep -f "hysteria/hysteria") ]] && [[ "$1" == "stop" ]]; then systemctl stop hysteria.service fi fi sleep 0.8 if [[ "$1" == "start" ]]; then if [[ -n $(pgrep -f "hysteria/hysteria") ]]; then echoContent green " ---> Xray-core version:${version}" else echoContent red "================================================== ===============" echoContent red "\n ---> Incorrect input, please re-enter" exit 0 fi elif [[ "$1" == "stop" ]]; then if [[ -z $(pgrep -f "hysteria/hysteria") ]]; then echoContent green " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)" else echoContent red " ---> The installation directory is not detected, please execute the script to install the content" echoContent red "\n================================================ =================" exit 0 fi fi } handleSingBox() { if [[ -f "/etc/systemd/system/sing-box.service" ]]; then if [[ -z $(pgrep -f "sing-box") ]] && [[ "$1" == "start" ]]; then singBoxMergeConfig systemctl start sing-box.service elif [[ -n $(pgrep -f "sing-box") ]] && [[ "$1" == "stop" ]]; then systemctl stop sing-box.service fi elif [[ -f "/etc/init.d/sing-box" ]]; then if [[ -z $(pgrep -f "sing-box") ]] && [[ "$1" == "start" ]]; then singBoxMergeConfig rc-service sing-box start elif [[ -n $(pgrep -f "sing-box") ]] && [[ "$1" == "stop" ]]; then rc-service sing-box stop fi fi sleep 1 if [[ "$1" == "start" ]]; then if [[ -n $(pgrep -f "sing-box") ]]; then echoContent green " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)" else echoContent red "================================================== ===============" echoContent yellow "2.Fallback v2ray-core" echo echoContent yellow "3.Close v2ray-core" exit 0 fi elif [[ "$1" == "stop" ]]; then if [[ -z $(pgrep -f "sing-box") ]]; then echoContent green " ---> Abandon the rollback version" else echoContent red "\n ---> Incorrect input, please re-enter" echoContent red " ---> Service startup failed, please check if there are logs printed in the terminal" exit 0 fi fi } # Manipulate xray handleXray() { if [[ -n $(find /bin /usr/bin -name "systemctl") ]] && [[ -n $(find /etc/systemd/system/ -name "xray.service") ]]; then if [[ -z $(pgrep -f "xray/xray") ]] && [[ "$1" == "start" ]]; then systemctl start xray.service elif [[ -n $(pgrep -f "xray/xray") ]] && [[ "$1" == "stop" ]]; then systemctl stop xray.service fi elif [[ -f "/etc/init.d/xray" ]]; then if [[ -z $(pgrep -f "xray/xray") ]] && [[ "$1" == "start" ]]; then rc-service xray start elif [[ -n $(pgrep -f "xray/xray") ]] && [[ "$1" == "stop" ]]; then rc-service xray stop fi fi sleep 0.8 if [[ "$1" == "start" ]]; then if [[ -n $(pgrep -f "xray/xray") ]]; then echoContent green " ---> Give up and reinstall" else echoContent red "V2Ray failed to start" echoContent red "Please manually execute [/etc/v2ray-agent/v2ray/v2ray -confdir /etc/v2ray-agent/v2ray/conf] and check the error log" exit 0 fi elif [[ "$1" == "stop" ]]; then if [[ -z $(pgrep -f "xray/xray") ]]; then echoContent green " ---> Abort update" else echoContent red "V2Ray failed to close" echoContent red "Please execute manually [ps -ef|grep -v grep|grep v2ray|awk '{print \$2}'|xargs kill -9]" exit 0 fi fi } # Read user data and initialize initXrayClients() { local type=",$1," local newUUID=$2 local newEmail=$3 if [[ -n "${newUUID}" ]]; then local newUser= newUser="{\"id\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"email\":\"${newEmail}-VLESS_TCP/TLS_Vision\"}" currentClients=$(echo "${currentClients}" | jq -r ". +=[${newUser}]") fi local users= users=[] while read -r user; do uuid=$(echo "${user}" | jq -r .id//.uuid) email=$(echo "${user}" | jq -r .email//.name | awk -F "[-]" '{print $1}') currentUser= if echo "${type}" | grep -q "0"; then currentUser="{\"id\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"email\":\"${email}-VLESS_TCP/TLS_Vision\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VLESS WS if echo "${type}" | grep -q ",1,"; then currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VLESS_WS\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VLESS XHTTP if echo "${type}" | grep -q ",12,"; then currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VLESS_Reality_XHTTP\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # trojan grpc if echo "${type}" | grep -q ",2,"; then currentUser="{\"password\":\"${uuid}\",\"email\":\"${email}-Trojan_gRPC\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VMess WS if echo "${type}" | grep -q ",3,"; then currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VMess_WS\",\"alterId\": 0}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # trojan tcp if echo "${type}" | grep -q ",4,"; then currentUser="{\"password\":\"${uuid}\",\"email\":\"${email}-trojan_tcp\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # vless grpc if echo "${type}" | grep -q ",5,"; then currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-vless_grpc\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # hysteria if echo "${type}" | grep -q ",6,"; then currentUser="{\"password\":\"${uuid}\",\"name\":\"${email}-singbox_hysteria2\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # vless reality vision if echo "${type}" | grep -q ",7,"; then currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-vless_reality_vision\",\"flow\":\"xtls-rprx-vision\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # vless reality grpc if echo "${type}" | grep -q ",8,"; then currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-vless_reality_grpc\",\"flow\":\"\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # tuic if echo "${type}" | grep -q ",9,"; then currentUser="{\"uuid\":\"${uuid}\",\"password\":\"${uuid}\",\"name\":\"${email}-singbox_tuic\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi done < <(echo "${currentClients}" | jq -c '.[]') echo "${users}" } initSingBoxClients() { local type=",$1," local newUUID=$2 local newName=$3 if [[ -n "${newUUID}" ]]; then local newUser= newUser="{\"uuid\":\"${newUUID}\",\"flow\":\"xtls-rprx-vision\",\"name\":\"${newName}-VLESS_TCP/TLS_Vision\"}" currentClients=$(echo "${currentClients}" | jq -r ". +=[${newUser}]") fi local users= users=[] while read -r user; do uuid=$(echo "${user}" | jq -r .uuid//.id//.password) name=$(echo "${user}" | jq -r .name//.email//.username | awk -F "[-]" '{print $1}') currentUser= # VLESS Vision if echo "${type}" | grep -q ",0,"; then currentUser="{\"uuid\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"name\":\"${name}-VLESS_TCP/TLS_Vision\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VLESS WS if echo "${type}" | grep -q ",1,"; then currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VLESS_WS\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VMess ws if echo "${type}" | grep -q ",3,"; then currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VMess_WS\",\"alterId\": 0}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # trojan if echo "${type}" | grep -q ",4,"; then currentUser="{\"password\":\"${uuid}\",\"name\":\"${name}-Trojan_TCP\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VLESS Reality Vision if echo "${type}" | grep -q ",7,"; then currentUser="{\"uuid\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"name\":\"${name}-VLESS_Reality_Vision\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VLESS Reality gRPC if echo "${type}" | grep -q ",8,"; then currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VLESS_Reality_gPRC\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # hysteria2 if echo "${type}" | grep -q ",6,"; then currentUser="{\"password\":\"${uuid}\",\"name\":\"${name}-singbox_hysteria2\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # tuic if echo "${type}" | grep -q ",9,"; then currentUser="{\"uuid\":\"${uuid}\",\"password\":\"${uuid}\",\"name\":\"${name}-singbox_tuic\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # naive if echo "${type}" | grep -q ",10,"; then currentUser="{\"password\":\"${uuid}\",\"username\":\"${name}-singbox_naive\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # VMess HTTPUpgrade if echo "${type}" | grep -q ",11,"; then currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VMess_HTTPUpgrade\",\"alterId\": 0}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi # anytls if echo "${type}" | grep -q ",13,"; then currentUser="{\"password\":\"${uuid}\",\"name\":\"${name}-anytls\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi if echo "${type}" | grep -q ",20,"; then currentUser="{\"username\":\"${uuid}\",\"password\":\"${uuid}\"}" users=$(echo "${users}" | jq -r ". +=[${currentUser}]") fi done < <(echo "${currentClients}" | jq -c '.[]') echo "${users}" } #Initialize hysteria port initHysteriaPort() { readSingBoxConfig if [[ -n "${hysteriaPort}" ]]; then read -r -p "Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:" historyHysteriaPortStatus if [[ "${historyHysteriaPortStatus}" == "y" ]]; then echoContent yellow "4.Open v2ray-core" else hysteriaPort= fi fi if [[ -z "${hysteriaPort}" ]]; then echoContent yellow "5.Restart v2ray-core" read -r -p "Port:" hysteriaPort if [[ -z "${hysteriaPort}" ]]; then hysteriaPort=$((RANDOM % 20001 + 10000)) fi fi if [[ -z ${hysteriaPort} ]]; then echoContent red "Hysteria startup failed" initHysteriaPort "$2" elif ((hysteriaPort < 1 || hysteriaPort > 65535)); then echoContent red "Please manually execute [/etc/v2ray-agent/hysteria/hysteria --log-level debug -c /etc/v2ray-agent/hysteria/conf/config.json server] to view the error log" initHysteriaPort "$2" fi allowPort "${hysteriaPort}" allowPort "${hysteriaPort}" "udp" } initHysteria2Network() { echoContent yellow "6.Update geosite, geoip" read -r -p "Download speed:" hysteria2ClientDownloadSpeed if [[ -z "${hysteria2ClientDownloadSpeed}" ]]; then hysteria2ClientDownloadSpeed=100 echoContent green " ---> Service started successfully" fi echoContent yellow "7.Set up automatic update of geo files [updated every morning]" read -r -p "Upload speed:" hysteria2ClientUploadSpeed if [[ -z "${hysteria2ClientUploadSpeed}" ]]; then hysteria2ClientUploadSpeed=50 echoContent green " ---> Service started successfully" fi } addFirewalldPortHopping() { local start=$1 local end=$2 local targetPort=$3 for port in $(seq "$start" "$end"); do sudo firewall-cmd --permanent --add-forward-port=port="${port}":proto=udp:toport="${targetPort}" done sudo firewall-cmd --reload } addPortHopping() { local type=$1 local targetPort=$2 if [[ -n "${portHoppingStart}" || -n "${portHoppingEnd}" ]]; then echoContent red "Hysteria shutdown failed" exit 0 fi if [[ "${release}" == "centos" ]]; then if ! systemctl status firewalld 2>/dev/null | grep -q "active (running)"; then echoContent red "Please execute manually [ps -ef|grep -v grep|grep hysteria|awk '{print \$2}'|xargs kill -9]" exit 0 fi fi echoContent skyBlue "------------------------Version-------------------------------" echoContent red "\n==============================================================" echoContent yellow "\n1.Only the last five versions can be rolled back" echoContent yellow "2.There is no guarantee that it will be able to be used normally after the rollback" echoContent yellow "3.If the rolled-back version does not support the current config, it will be unable to connect, so operate with caution" echoContent yellow "1.Upgrade Xray-core" echoContent yellow "2.Upgrade Xray-core preview version" echoContent yellow "3.Fallback Xray-core" echoContent yellow "4.Close Xray-core" echoContent yellow "5.Open Xray-core" read -r -p "Range:" portHoppingRange if [[ -z "${portHoppingRange}" ]]; then echoContent red "Tuic startup failed" addPortHopping "${type}" "${targetPort}" elif echo "${portHoppingRange}" | grep -q "-"; then local portStart= local portEnd= portStart=$(echo "${portHoppingRange}" | awk -F '-' '{print $1}') portEnd=$(echo "${portHoppingRange}" | awk -F '-' '{print $2}') if [[ -z "${portStart}" || -z "${portEnd}" ]]; then echoContent red "Please manually execute [/etc/v2ray-agent/tuic/tuic -c /etc/v2ray-agent/tuic/conf/config.json] and check the error log" addPortHopping "${type}" "${targetPort}" elif ((portStart < 30000 || portStart > 40000 || portEnd < 30000 || portEnd > 40000 || portEnd < portStart)); then echoContent red "Tuic failed to close" addPortHopping "${type}" "${targetPort}" else echoContent green " ---> Configure V2Ray to start automatically at boot" if [[ "${release}" == "centos" ]]; then sudo firewall-cmd --permanent --add-masquerade sudo firewall-cmd --reload addFirewalldPortHopping "${portStart}" "${portEnd}" "${targetPort}" if ! sudo firewall-cmd --list-forward-ports | grep -q "toport=${targetPort}"; then echoContent red "Please execute manually [ps -ef|grep -v grep|grep tuic|awk '{print \$2}'|xargs kill -9]" exit 0 fi else iptables -t nat -A PREROUTING -p udp --dport "${portStart}:${portEnd}" -m comment --comment "mack-a_${type}_portHopping" -j DNAT --to-destination ":${targetPort}" sudo netfilter-persistent save if ! iptables-save | grep -q "mack-a_${type}_portHopping"; then echoContent red "Xray startup failed" exit 0 fi fi allowPort "${portStart}:${portEnd}" udp echoContent green " ---> Configure Hysteria to start automatically at boot" fi fi } readPortHopping() { local type=$1 local targetPort=$2 local portHoppingStart= local portHoppingEnd= if [[ "${release}" == "centos" ]]; then portHoppingStart=$(sudo firewall-cmd --list-forward-ports | grep "toport=${targetPort}" | head -1 | cut -d ":" -f 1 | cut -d "=" -f 2) portHoppingEnd=$(sudo firewall-cmd --list-forward-ports | grep "toport=${targetPort}" | tail -n 1 | cut -d ":" -f 1 | cut -d "=" -f 2) else if iptables-save | grep -q "mack-a_${type}_portHopping"; then local portHopping= portHopping=$(iptables-save | grep "mack-a_${type}_portHopping" | cut -d " " -f 8) portHoppingStart=$(echo "${portHopping}" | cut -d ":" -f 1) portHoppingEnd=$(echo "${portHopping}" | cut -d ":" -f 2) fi fi if [[ "${type}" == "hysteria2" ]]; then hysteria2PortHoppingStart="${portHoppingStart}" hysteria2PortHoppingEnd=${portHoppingEnd} hysteria2PortHopping="${portHoppingStart}-${portHoppingEnd}" elif [[ "${type}" == "tuic" ]]; then tuicPortHoppingStart="${portHoppingStart}" tuicPortHoppingEnd="${portHoppingEnd}" # tuicPortHopping="${portHoppingStart}-${portHoppingEnd}" fi } deletePortHoppingRules() { local type=$1 local start=$2 local end=$3 local targetPort=$4 if [[ "${release}" == "centos" ]]; then for port in $(seq "${start}" "${end}"); do sudo firewall-cmd --permanent --remove-forward-port=port="${port}":proto=udp:toport="${targetPort}" done sudo firewall-cmd --reload else iptables -t nat -L PREROUTING --line-numbers | grep "mack-a_${type}_portHopping" | awk '{print $1}' | while read -r line; do iptables -t nat -D PREROUTING 1 sudo netfilter-persistent save done fi } portHoppingMenu() { local type=$1 # Determine whether iptables exists if ! find /usr/bin /usr/sbin | grep -q -w iptables; then echoContent red "Please manually execute the following command [/etc/v2ray-agent/xray/xray -confdir /etc/v2ray-agent/xray/conf] and feedback the error log" exit 0 fi local targetPort= local portHoppingStart= local portHoppingEnd= if [[ "${type}" == "hysteria2" ]]; then readPortHopping "${type}" "${singBoxHysteria2Port}" targetPort=${singBoxHysteria2Port} portHoppingStart=${hysteria2PortHoppingStart} portHoppingEnd=${hysteria2PortHoppingEnd} elif [[ "${type}" == "tuic" ]]; then readPortHopping "${type}" "${singBoxTuicPort}" targetPort=${singBoxTuicPort} portHoppingStart=${tuicPortHoppingStart} portHoppingEnd=${tuicPortHoppingEnd} fi echoContent skyBlue "\nProgress$1/${totalProgress}: V2Ray version management" echoContent red "\n==============================================================" echoContent yellow "6.Restart Xray-core" echoContent yellow "7.Update geosite, geoip" echoContent yellow "8.Set up automatic update of geo files [updated every morning]" read -r -p "range:" selectPortHoppingStatus if [[ "${selectPortHoppingStatus}" == "1" ]]; then addPortHopping "${type}" "${targetPort}" elif [[ "${selectPortHoppingStatus}" == "2" ]]; then deletePortHoppingRules "${type}" "${portHoppingStart}" "${portHoppingEnd}" "${targetPort}" echoContent green " ---> Configuring Tuic to start automatically at boot" elif [[ "${selectPortHoppingStatus}" == "3" ]]; then if [[ -n "${portHoppingStart}" && -n "${portHoppingEnd}" ]]; then echoContent green " ---> Configure Xray to start automatically at boot" else echoContent yellow "\n1.Only the last five versions can be rolled back" fi else portHoppingMenu fi } #Initialize tuic port initTuicPort() { readSingBoxConfig if [[ -n "${tuicPort}" ]]; then read -r -p "Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:" historyTuicPortStatus if [[ "${historyTuicPortStatus}" == "y" ]]; then echoContent yellow "2.There is no guarantee that it will be able to be used normally after the rollback" else tuicPort= fi fi if [[ -z "${tuicPort}" ]]; then echoContent yellow "3.If the rolled-back version does not support the current config, it will be unable to connect, so operate with caution" read -r -p "Port:" tuicPort if [[ -z "${tuicPort}" ]]; then tuicPort=$((RANDOM % 20001 + 10000)) fi fi if [[ -z ${tuicPort} ]]; then echoContent red "xray failed to close" initTuicPort "$2" elif ((tuicPort < 1 || tuicPort > 65535)); then echoContent red "Please execute manually [ps -ef|grep -v grep|grep xray|awk '{print \$2}'|xargs kill -9]" initTuicPort "$2" fi echoContent green " ---> V2Ray started successfully" allowPort "${tuicPort}" allowPort "${tuicPort}" "udp" } # Initialize tuic protocol initTuicProtocol() { if [[ -n "${tuicAlgorithm}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Previous algorithm found. Use it? [y/n]:" historyTuicAlgorithm if [[ "${historyTuicAlgorithm}" != "y" ]]; then tuicAlgorithm= else echoContent yellow "\nSource https://github.com/Loyalsoldier/v2ray-rules-dat" fi elif [[ -n "${tuicAlgorithm}" && -n "${lastInstallationConfig}" ]]; then echoContent yellow "The configuration file last installed for this protocol [${protocol}] was not read, and the first uuid of the configuration file was used" fi if [[ -z "${tuicAlgorithm}" ]]; then echoContent skyBlue "------------------------Version-------------------------------" echoContent red "==============================================================" echoContent yellow "\n ---> Port: ${hysteriaPort}" echoContent yellow "2.cubic" echoContent yellow "3.new_reno" echoContent red "==============================================================" read -r -p "Please select:" selectTuicAlgorithm case ${selectTuicAlgorithm} in 1) tuicAlgorithm="bbr" ;; 2) tuicAlgorithm="cubic" ;; 3) tuicAlgorithm="new_reno" ;; *) tuicAlgorithm="bbr" ;; esac echoContent yellow "Please enter the Hysteria port [enter random 10000-30000], cannot be repeated with other services" fi } #initTuicConfig() { # # initTuicPort # initTuicProtocol # cat </etc/v2ray-agent/tuic/conf/config.json #{ # "server": "[::]:${tuicPort}", # "users": $(initXrayClients 9), # "certificate": "/etc/v2ray-agent/tls/${currentHost}.crt", # "private_key": "/etc/v2ray-agent/tls/${currentHost}.key", # "congestion_control":"${tuicAlgorithm}", # "alpn": ["h3"], # "log_level": "warn" #} #EOF #} addSingBoxRouteRule() { local outboundTag=$1 local domainList=$2 local routingName=$3 if [[ -f "${singBoxConfigPath}${routingName}.json" ]]; then read -r -p "Previous configuration found. Keep it? [y/n]:" historyRouteStatus if [[ "${historyRouteStatus}" == "y" ]]; then domainList="${domainList},$(jq -rc .route.rules[0].rule_set[] "${singBoxConfigPath}${routingName}.json" | awk -F "[_]" '{print $1}' | paste -sd ',')" domainList="${domainList},$(jq -rc .route.rules[0].domain_regex[] "${singBoxConfigPath}${routingName}.json" | awk -F "[*]" '{print $2}' | paste -sd ',' | sed 's/\\//g')" fi fi local rules= rules=$(initSingBoxRules "${domainList}" "${routingName}") local domainRules= domainRules=$(echo "${rules}" | jq .domainRules) local ruleSet= ruleSet=$(echo "${rules}" | jq .ruleSet) local ruleSetTag=[] if [[ "$(echo "${ruleSet}" | jq '.|length')" != "0" ]]; then ruleSetTag=$(echo "${ruleSet}" | jq '.|map(.tag)') fi if [[ -n "${singBoxConfigPath}" ]]; then cat <"${singBoxConfigPath}${routingName}.json" { "route": { "rules": [ { "rule_set":${ruleSetTag}, "domain_regex":${domainRules}, "outbound": "${outboundTag}" } ], "rule_set":${ruleSet} } } EOF jq 'if .route.rule_set == [] then del(.route.rule_set) else . end' "${singBoxConfigPath}${routingName}.json" >"${singBoxConfigPath}${routingName}_tmp.json" && mv "${singBoxConfigPath}${routingName}_tmp.json" "${singBoxConfigPath}${routingName}.json" fi } removeSingBoxRouteRule() { local outboundTag=$1 local delRules if [[ -f "${singBoxConfigPath}${outboundTag}_route.json" ]]; then delRules=$(jq -r 'del(.route.rules[]|select(.outbound=="'"${outboundTag}"'"))' "${singBoxConfigPath}${outboundTag}_route.json") echo "${delRules}" >"${singBoxConfigPath}${outboundTag}_route.json" fi } addSingBoxOutbound() { local tag=$1 local type="ipv4" local detour=$2 if echo "${tag}" | grep -q "IPv6"; then type=ipv6 fi if [[ -n "${detour}" ]]; then cat <"${singBoxConfigPath}${tag}.json" { "outbounds": [ { "type": "direct", "tag": "${tag}", "detour": "${detour}", "domain_strategy": "${type}_only" } ] } EOF elif echo "${tag}" | grep -q "direct"; then cat <"${singBoxConfigPath}${tag}.json" { "outbounds": [ { "type": "direct", "tag": "${tag}" } ] } EOF elif echo "${tag}" | grep -q "block"; then cat <"${singBoxConfigPath}${tag}.json" { "outbounds": [ { "type": "block", "tag": "${tag}" } ] } EOF else cat <"${singBoxConfigPath}${tag}.json" { "outbounds": [ { "type": "direct", "tag": "${tag}", "domain_strategy": "${type}_only" } ] } EOF fi } addXrayOutbound() { local tag=$1 local domainStrategy= if echo "${tag}" | grep -q "IPv4"; then domainStrategy="ForceIPv4" elif echo "${tag}" | grep -q "IPv6"; then domainStrategy="ForceIPv6" fi if [[ -n "${domainStrategy}" ]]; then cat <"/etc/v2ray-agent/xray/conf/${tag}.json" { "outbounds":[ { "protocol":"freedom", "settings":{ "domainStrategy":"${domainStrategy}" }, "tag":"${tag}" } ] } EOF fi # direct if echo "${tag}" | grep -q "direct"; then cat <"/etc/v2ray-agent/xray/conf/${tag}.json" { "outbounds":[ { "protocol":"freedom", "settings": { "domainStrategy":"UseIP" }, "tag":"${tag}" } ] } EOF fi # blackhole if echo "${tag}" | grep -q "blackhole"; then cat <"/etc/v2ray-agent/xray/conf/${tag}.json" { "outbounds":[ { "protocol":"blackhole", "tag":"${tag}" } ] } EOF fi # socks5 outbound if echo "${tag}" | grep -q "socks5"; then cat <"/etc/v2ray-agent/xray/conf/${tag}.json" { "outbounds": [ { "protocol": "socks", "tag": "${tag}", "settings": { "servers": [ { "address": "${socks5RoutingOutboundIP}", "port": ${socks5RoutingOutboundPort}, "users": [ { "user": "${socks5RoutingOutboundUserName}", "pass": "${socks5RoutingOutboundPassword}" } ] } ] } } ] } EOF fi if echo "${tag}" | grep -q "wireguard_out_IPv4"; then cat <"/etc/v2ray-agent/xray/conf/${tag}.json" { "outbounds": [ { "protocol": "wireguard", "settings": { "secretKey": "${secretKeyWarpReg}", "address": [ "${address}" ], "peers": [ { "publicKey": "${publicKeyWarpReg}", "allowedIPs": [ "0.0.0.0/0", "::/0" ], "endpoint": "162.159.192.1:2408" } ], "reserved": ${reservedWarpReg}, "mtu": 1280 }, "tag": "${tag}" } ] } EOF fi if echo "${tag}" | grep -q "wireguard_out_IPv6"; then cat <"/etc/v2ray-agent/xray/conf/${tag}.json" { "outbounds": [ { "protocol": "wireguard", "settings": { "secretKey": "${secretKeyWarpReg}", "address": [ "${address}" ], "peers": [ { "publicKey": "${publicKeyWarpReg}", "allowedIPs": [ "0.0.0.0/0", "::/0" ], "endpoint": "162.159.192.1:2408" } ], "reserved": ${reservedWarpReg}, "mtu": 1280 }, "tag": "${tag}" } ] } EOF fi if echo "${tag}" | grep -q "vmess-out"; then cat <"/etc/v2ray-agent/xray/conf/${tag}.json" { "outbounds": [ { "tag": "${tag}", "protocol": "vmess", "streamSettings": { "network": "ws", "security": "tls", "tlsSettings": {}, "wsSettings": { "path": "${setVMessWSTLSPath}" } }, "mux": { "enabled": true, "concurrency": 8 }, "settings": { "vnext": [ { "address": "${setVMessWSTLSAddress}", "port": "${setVMessWSTLSPort}", "users": [ { "id": "${setVMessWSTLSUUID}", "security": "auto", "alterId": 0 } ] } ] } } ] } EOF fi } removeXrayOutbound() { local tag=$1 if [[ -f "/etc/v2ray-agent/xray/conf/${tag}.json" ]]; then rm "/etc/v2ray-agent/xray/conf/${tag}.json" >/dev/null 2>&1 fi } removeSingBoxConfig() { local tag=$1 if [[ -f "${singBoxConfigPath}${tag}.json" ]]; then rm "${singBoxConfigPath}${tag}.json" fi } addSingBoxWireGuardEndpoints() { local type=$1 readConfigWarpReg cat <"${singBoxConfigPath}wireguard_endpoints_${type}.json" { "endpoints": [ { "type": "wireguard", "tag": "wireguard_endpoints_${type}", "address": [ "${address}" ], "private_key": "${secretKeyWarpReg}", "peers": [ { "address": "162.159.192.1", "port": 2408, "public_key": "${publicKeyWarpReg}", "reserved":${reservedWarpReg}, "allowed_ips": ["0.0.0.0/0","::/0"] } ] } ] } EOF } initSingBoxHysteria2Config() { echoContent skyBlue "------------------------------------------------- ---------------" initHysteriaPort initHysteria2Network cat </etc/v2ray-agent/sing-box/conf/config/hysteria2.json { "inbounds": [ { "type": "hysteria2", "listen": "::", "listen_port": ${hysteriaPort}, "users": $(initXrayClients 6), "up_mbps":${hysteria2ClientDownloadSpeed}, "down_mbps":${hysteria2ClientUploadSpeed}, "tls": { "enabled": true, "server_name":"${currentHost}", "alpn": [ "h3" ], "certificate_path": "/etc/v2ray-agent/tls/${currentHost}.crt", "key_path": "/etc/v2ray-agent/tls/${currentHost}.key" } } ] } EOF } singBoxTuicInstall() { if ! echo "${currentInstallProtocolType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,"; then echoContent red " ---> Port cannot be empty" exit 0 fi totalProgress=5 installSingBox 1 selectCustomInstallType=",9," initSingBoxConfig custom 2 true installSingBoxService 3 reloadCore showAccounts 4 } singBoxHysteria2Install() { if ! echo "${currentInstallProtocolType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,"; then echoContent red " ---> The port is illegal" exit 0 fi totalProgress=5 installSingBox 1 selectCustomInstallType=",6," initSingBoxConfig custom 2 true installSingBoxService 3 reloadCore showAccounts 4 } singBoxMergeConfig() { rm /etc/v2ray-agent/sing-box/conf/config.json >/dev/null 2>&1 /etc/v2ray-agent/sing-box/sing-box merge config.json -C /etc/v2ray-agent/sing-box/conf/config/ -D /etc/v2ray-agent/sing-box/conf/ >/dev/null 2>&1 } #initXrayFrontingConfig() { # if [[ -z "${configPath}" ]]; then # menu # exit 0 # fi # if [[ "${coreInstallType}" != "1" ]]; then # fi # local xtlsType= # if echo ${currentInstallProtocolType} | grep -q trojan; then # xtlsType=VLESS # else # xtlsType=Trojan # fi # # echoContent red "\n==============================================================" # # echoContent red "==============================================================" # if [[ "${selectType}" == "1" ]]; then # # if [[ "${xtlsType}" == "Trojan" ]]; then # # local VLESSConfig # VLESSConfig=$(cat ${configPath}${frontingType}.json) # VLESSConfig=${VLESSConfig//"id"/"password"} # VLESSConfig=${VLESSConfig//VLESSTCP/TrojanTCPXTLS} # VLESSConfig=${VLESSConfig//VLESS/Trojan} # VLESSConfig=${VLESSConfig//"vless"/"trojan"} # VLESSConfig=${VLESSConfig//"id"/"password"} # # echo "${VLESSConfig}" | jq . >${configPath}02_trojan_TCP_inbounds.json # rm ${configPath}${frontingType}.json # elif [[ "${xtlsType}" == "VLESS" ]]; then # # local VLESSConfig # VLESSConfig=$(cat ${configPath}02_trojan_TCP_inbounds.json) # VLESSConfig=${VLESSConfig//"password"/"id"} # VLESSConfig=${VLESSConfig//TrojanTCPXTLS/VLESSTCP} # VLESSConfig=${VLESSConfig//Trojan/VLESS} # VLESSConfig=${VLESSConfig//"trojan"/"vless"} # VLESSConfig=${VLESSConfig//"password"/"id"} # # echo "${VLESSConfig}" | jq . >${configPath}02_VLESS_TCP_inbounds.json # rm ${configPath}02_trojan_TCP_inbounds.json # fi # reloadCore # fi # # exit 0 #} initSingBoxPort() { local port=$1 if [[ -n "${port}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Previous port found. Use it? [y/n]:" historyPort if [[ "${historyPort}" != "y" ]]; then port= else echo "${port}" fi elif [[ -n "${port}" && -n "${lastInstallationConfig}" ]]; then echo "${port}" fi if [[ -z "${port}" ]]; then read -r -p 'Enter a custom port [must be valid and unique; Enter for random]:' port if [[ -z "${port}" ]]; then port=$((RANDOM % 50001 + 10000)) fi if ((port >= 1 && port <= 65535)); then allowPort "${port}" allowPort "${port}" "udp" echo "${port}" else echoContent red "================================================== ===============" exit 0 fi fi } #Initialize Xray configuration file initXrayConfig() { echoContent skyBlue "\nProgress$1/${totalProgress}: Xray version management" echo local uuid= local addClientsStatus= if [[ -n "${currentUUID}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Read the last installation record. Do you want to use the UUID from the last installation? [y/n]:" historyUUIDStatus if [[ "${historyUUIDStatus}" == "y" ]]; then addClientsStatus=true echoContent green " ---> V2Ray closed successfully" fi elif [[ -n "${currentUUID}" && -n "${lastInstallationConfig}" ]]; then addClientsStatus=true fi if [[ -z "${addClientsStatus}" ]]; then echoContent yellow "1.udp(QUIC)(default)" read -r -p 'UUID:' customUUID if [[ -n ${customUUID} ]]; then uuid=${customUUID} else uuid=$(/etc/v2ray-agent/xray/xray uuid) fi echoContent yellow "2.faketcp" read -r -p 'Username:' customEmail if [[ -z ${customEmail} ]]; then customEmail="$(echo "${uuid}" | cut -d "-" -f 1)-VLESS_TCP/TLS_Vision" fi fi if [[ -z "${addClientsStatus}" && -z "${uuid}" ]]; then addClientsStatus= echoContent red "================================================== ===============" uuid=$(/etc/v2ray-agent/xray/xray uuid) fi if [[ -n "${uuid}" ]]; then currentClients='[{"id":"'${uuid}'","add":"'${add}'","flow":"xtls-rprx-vision","email":"'${customEmail}'"}]' echoContent green "\n ${customEmail}:${uuid}" echo fi # log #log if [[ ! -f "/etc/v2ray-agent/xray/conf/00_log.json" ]]; then cat </etc/v2ray-agent/xray/conf/00_log.json { "log": { "error": "/etc/v2ray-agent/xray/error.log", "loglevel": "warning", "dnsLog": false } } EOF fi if [[ ! -f "/etc/v2ray-agent/xray/conf/12_policy.json" ]]; then cat </etc/v2ray-agent/xray/conf/12_policy.json { "policy": { "levels": { "0": { "handshake": $((1 + RANDOM % 4)), "connIdle": $((250 + RANDOM % 51)) } } } } EOF fi addXrayOutbound "z_direct_outbound" # dns # dns if [[ ! -f "/etc/v2ray-agent/xray/conf/11_dns.json" ]]; then cat </etc/v2ray-agent/xray/conf/11_dns.json { "dns": { "servers": [ "localhost" ] } } EOF fi # routing cat </etc/v2ray-agent/xray/conf/09_routing.json { "routing": { "rules": [ { "type": "field", "domain": [ "domain:gstatic.com", "domain:googleapis.com", "domain:googleapis.cn" ], "outboundTag": "z_direct_outbound" } ] } } EOF # VLESS_TCP_TLS_Vision local fallbacksList='{"dest":31300,"xver":1},{"alpn":"h2","dest":31302,"xver":1}' # trojan if echo "${selectCustomInstallType}" | grep -q ",4," || [[ "$1" == "all" ]]; then fallbacksList='{"dest":31296,"xver":1},{"alpn":"h2","dest":31302,"xver":1}' cat </etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json { "inbounds":[ { "port": 31296, "listen": "127.0.0.1", "protocol": "trojan", "tag":"trojanTCP", "settings": { "clients": $(initXrayClients 4), "fallbacks":[ { "dest":"31300", "xver":1 } ] }, "streamSettings": { "network": "tcp", "security": "none", "tcpSettings": { "acceptProxyProtocol": true } } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json >/dev/null 2>&1 fi # VLESS_WS_TLS if echo "${selectCustomInstallType}" | grep -q ",1," || [[ "$1" == "all" ]]; then fallbacksList=${fallbacksList}',{"path":"/'${customPath}'ws","dest":31297,"xver":1}' cat </etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json { "inbounds":[ { "port": 31297, "listen": "127.0.0.1", "protocol": "vless", "tag":"VLESSWS", "settings": { "clients": $(initXrayClients 1), "decryption": "none" }, "streamSettings": { "network": "ws", "security": "none", "wsSettings": { "acceptProxyProtocol": true, "path": "/${customPath}ws" } } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json >/dev/null 2>&1 fi # VLESS_Reality_XHTTP_TLS if echo "${selectCustomInstallType}" | grep -q ",12," || [[ "$1" == "all" ]]; then initXrayXHTTPort initRealityClientServersName initRealityKey initRealityMldsa65 cat </etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json { "inbounds":[ { "port": ${xHTTPort}, "listen": "0.0.0.0", "protocol": "vless", "tag":"VLESSRealityXHTTP", "settings": { "clients": $(initXrayClients 12), "decryption": "none" }, "streamSettings": { "network": "xhttp", "security": "reality", "realitySettings": { "show": false, "target": "${realityServerName}:${realityDomainPort}", "xver": 0, "serverNames": [ "${realityServerName}" ], "privateKey": "${realityPrivateKey}", "publicKey": "${realityPublicKey}", "mldsa65Seed": "${realityMldsa65Seed}", "mldsa65Verify": "${realityMldsa65Verify}", "minClientVer": "1.8.2", "maxTimeDiff": 70000, "shortIds": [ "", "6ba85179e30d4fc2" ] }, "xhttpSettings": { "host": "${realityServerName}", "path": "/${customPath}xHTTP", "mode": "auto" } } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",3," || [[ "$1" == "all" ]]; then fallbacksList=${fallbacksList}',{"path":"/'${customPath}'vws","dest":31299,"xver":1}' cat </etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json { "inbounds":[ { "listen": "127.0.0.1", "port": 31299, "protocol": "vmess", "tag":"VMessWS", "settings": { "clients": $(initXrayClients 3) }, "streamSettings": { "network": "ws", "security": "none", "wsSettings": { "acceptProxyProtocol": true, "path": "/${customPath}vws" } } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json >/dev/null 2>&1 fi # VLESS_gRPC # if echo "${selectCustomInstallType}" | grep -q ",5," || [[ "$1" == "all" ]]; then # cat </etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json #{ # "inbounds":[ # { # "port": 31301, # "listen": "127.0.0.1", # "protocol": "vless", # "tag":"VLESSGRPC", # "settings": { # "clients": $(initXrayClients 5), # "decryption": "none" # }, # "streamSettings": { # "network": "grpc", # "grpcSettings": { # "serviceName": "${customPath}grpc" # } # } # } # ] #} #EOF # elif [[ -z "$3" ]]; then # rm /etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json >/dev/null 2>&1 # fi # VLESS Vision if echo "${selectCustomInstallType}" | grep -q ",0," || [[ "$1" == "all" ]]; then cat </etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json { "inbounds":[ { "port": ${port}, "protocol": "vless", "tag":"VLESSTCP", "settings": { "clients":$(initXrayClients 0), "decryption": "none", "fallbacks": [ ${fallbacksList} ] }, "add": "${add}", "streamSettings": { "network": "tcp", "security": "tls", "tlsSettings": { "rejectUnknownSni": true, "minVersion": "1.2", "certificates": [ { "certificateFile": "/etc/v2ray-agent/tls/${domain}.crt", "keyFile": "/etc/v2ray-agent/tls/${domain}.key", "ocspStapling": 3600 } ] } } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json >/dev/null 2>&1 fi # VLESS_TCP/reality if echo "${selectCustomInstallType}" | grep -q ",7," || [[ "$1" == "all" ]]; then echoContent skyBlue "------------------------Version-------------------------------" initXrayRealityPort initRealityClientServersName initRealityKey initRealityMldsa65 cat </etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json { "inbounds": [ { "tag": "dokodemo-in-VLESSReality", "port": ${realityPort}, "protocol": "dokodemo-door", "settings": { "address": "127.0.0.1", "port": 45987, "network": "tcp" }, "sniffing": { "enabled": true, "destOverride": [ "tls" ], "routeOnly": true } }, { "listen": "127.0.0.1", "port": 45987, "protocol": "vless", "settings": { "clients": $(initXrayClients 7), "decryption": "none", "fallbacks":[ ] }, "streamSettings": { "network": "tcp", "security": "reality", "realitySettings": { "show": false, "target": "${realityServerName}:${realityDomainPort}", "xver": 0, "serverNames": [ "${realityServerName}" ], "privateKey": "${realityPrivateKey}", "publicKey": "${realityPublicKey}", "mldsa65Seed": "${realityMldsa65Seed}", "mldsa65Verify": "${realityMldsa65Verify}", "minClientVer": "1.8.2", "maxTimeDiff": 70000, "shortIds": [ "", "6ba85179e30d4fc2" ] } }, "sniffing": { "enabled": true, "destOverride": [ "http", "tls", "quic" ], "routeOnly": true } } ], "routing": { "rules": [ { "inboundTag": [ "dokodemo-in" ], "domain": [ "${realityServerName}" ], "outboundTag": "z_direct_outbound" }, { "inboundTag": [ "dokodemo-in" ], "outboundTag": "blackhole_out" } ] } } EOF # cat </etc/v2ray-agent/xray/conf/08_VLESS_vision_gRPC_inbounds.json #{ # "inbounds": [ # { # "port": 31305, # "listen": "127.0.0.1", # "protocol": "vless", # "tag": "VLESSRealityGRPC", # "settings": { # "clients": $(initXrayClients 8), # "decryption": "none" # }, # "streamSettings": { # "network": "grpc", # "grpcSettings": { # "serviceName": "grpc", # "multiMode": true # }, # "sockopt": { # "acceptProxyProtocol": true # } # } # } # ] #} #EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1 rm /etc/v2ray-agent/xray/conf/08_VLESS_vision_gRPC_inbounds.json >/dev/null 2>&1 fi installSniffing if [[ -z "$3" ]]; then removeXrayOutbound wireguard_out_IPv4_route removeXrayOutbound wireguard_out_IPv6_route removeXrayOutbound wireguard_outbound removeXrayOutbound IPv4_out removeXrayOutbound IPv6_out removeXrayOutbound socks5_outbound removeXrayOutbound blackhole_out removeXrayOutbound wireguard_out_IPv6 removeXrayOutbound wireguard_out_IPv4 addXrayOutbound z_direct_outbound addXrayOutbound blackhole_out fi } initTCPBrutal() { echoContent skyBlue "------------------------------------------------- ---------------" read -r -p "Use TCP_Brutal? [y/n]:" tcpBrutalStatus if [[ "${tcpBrutalStatus}" == "y" ]]; then read -r -p "Enter local peak download speed (default: 100 Mbps):" tcpBrutalClientDownloadSpeed if [[ -z "${tcpBrutalClientDownloadSpeed}" ]]; then tcpBrutalClientDownloadSpeed=100 fi read -r -p "Enter local peak upload speed (default: 50 Mbps):" tcpBrutalClientUploadSpeed if [[ -z "${tcpBrutalClientUploadSpeed}" ]]; then tcpBrutalClientUploadSpeed=50 fi fi } initSingBoxConfig() { echoContent skyBlue "------------------------Version-------------------------------" echo local uuid= local addClientsStatus= local sslDomain= if [[ -n "${domain}" ]]; then sslDomain="${domain}" elif [[ -n "${currentHost}" ]]; then sslDomain="${currentHost}" fi if [[ -n "${currentUUID}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Read the last user configuration. Do you want to use the last installed configuration? [y/n]:" historyUUIDStatus if [[ "${historyUUIDStatus}" == "y" ]]; then addClientsStatus=true echoContent green " ---> Hysteria started successfully" fi elif [[ -n "${currentUUID}" && -n "${lastInstallationConfig}" ]]; then addClientsStatus=true fi if [[ -z "${addClientsStatus}" ]]; then echoContent yellow "3.wechat-video" read -r -p 'UUID:' customUUID if [[ -n ${customUUID} ]]; then uuid=${customUUID} else uuid=$(/etc/v2ray-agent/sing-box/sing-box generate uuid) fi echoContent yellow "\n ---> Protocol: ${hysteriaProtocol}\n" read -r -p 'Username:' customEmail if [[ -z ${customEmail} ]]; then customEmail="$(echo "${uuid}" | cut -d "-" -f 1)-VLESS_TCP/TLS_Vision" fi fi if [[ -z "${addClientsStatus}" && -z "${uuid}" ]]; then addClientsStatus= echoContent red " ---> Already added, cannot be added repeatedly, can be deleted and re-added" uuid=$(/etc/v2ray-agent/sing-box/sing-box generate uuid) fi if [[ -n "${uuid}" ]]; then currentClients='[{"uuid":"'${uuid}'","flow":"xtls-rprx-vision","name":"'${customEmail}'"}]' echoContent yellow "\n ${customEmail}:${uuid}" fi # VLESS Vision if echo "${selectCustomInstallType}" | grep -q ",0," || [[ "$1" == "all" ]]; then echoContent yellow "Please enter the average delay from local to server, please fill it in according to the actual situation (default: 180, unit: ms)" echoContent skyBlue "\nProgress$1/${totalProgress}: Verify service startup status" echo mapfile -t result < <(initSingBoxPort "${singBoxVLESSVisionPort}") echoContent green " ---> Hysteria closed successfully" checkDNSIP "${domain}" removeNginxDefaultConf handleSingBox stop checkPortOpen "${result[-1]}" "${domain}" cat </etc/v2ray-agent/sing-box/conf/config/02_VLESS_TCP_inbounds.json { "inbounds":[ { "type": "vless", "listen":"::", "listen_port":${result[-1]}, "tag":"VLESSTCP", "users":$(initSingBoxClients 0), "tls":{ "server_name": "${sslDomain}", "enabled": true, "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/02_VLESS_TCP_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",1," || [[ "$1" == "all" ]]; then echoContent yellow "\n ---> Delay: ${hysteriaLag}\n" echoContent skyBlue "\nProgress$1/${totalProgress}: Configure V2Ray to start automatically at boot" echo mapfile -t result < <(initSingBoxPort "${singBoxVLESSWSPort}") echoContent green " ---> Tuic started successfully" checkDNSIP "${domain}" removeNginxDefaultConf handleSingBox stop randomPathFunction checkPortOpen "${result[-1]}" "${domain}" cat </etc/v2ray-agent/sing-box/conf/config/03_VLESS_WS_inbounds.json { "inbounds":[ { "type": "vless", "listen":"::", "listen_port":${result[-1]}, "tag":"VLESSWS", "users":$(initSingBoxClients 1), "tls":{ "server_name": "${sslDomain}", "enabled": true, "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" }, "transport": { "type": "ws", "path": "/${currentPath}ws", "max_early_data": 2048, "early_data_header_name": "Sec-WebSocket-Protocol" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/03_VLESS_WS_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",3," || [[ "$1" == "all" ]]; then echoContent yellow "Please enter the local bandwidth peak downstream speed (default: 100, unit: Mbps)" echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Hysteria to start automatically at boot" echo mapfile -t result < <(initSingBoxPort "${singBoxVMessWSPort}") echoContent green " ---> Tuic closed successfully" checkDNSIP "${domain}" removeNginxDefaultConf handleSingBox stop randomPathFunction checkPortOpen "${result[-1]}" "${domain}" cat </etc/v2ray-agent/sing-box/conf/config/05_VMess_WS_inbounds.json { "inbounds":[ { "type": "vmess", "listen":"::", "listen_port":${result[-1]}, "tag":"VMessWS", "users":$(initSingBoxClients 3), "tls":{ "server_name": "${sslDomain}", "enabled": true, "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" }, "transport": { "type": "ws", "path": "/${currentPath}", "max_early_data": 2048, "early_data_header_name": "Sec-WebSocket-Protocol" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/05_VMess_WS_inbounds.json >/dev/null 2>&1 fi # VLESS_Reality_Vision if echo "${selectCustomInstallType}" | grep -q ",7," || [[ "$1" == "all" ]]; then echoContent yellow "\n --->Download speed: ${hysteriaClientDownloadSpeed}\n" initRealityClientServersName initRealityKey echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Tuic to start automatically at boot" echo mapfile -t result < <(initSingBoxPort "${singBoxVLESSRealityVisionPort}") echoContent green " ---> Xray started successfully" cat </etc/v2ray-agent/sing-box/conf/config/07_VLESS_vision_reality_inbounds.json { "inbounds": [ { "type": "vless", "listen":"::", "listen_port":${result[-1]}, "tag": "VLESSReality", "users":$(initSingBoxClients 7), "tls": { "enabled": true, "server_name": "${realityServerName}", "reality": { "enabled": true, "handshake":{ "server": "${realityServerName}", "server_port":${realityDomainPort} }, "private_key": "${realityPrivateKey}", "short_id": [ "", "6ba85179e30d4fc2" ] } } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",8," || [[ "$1" == "all" ]]; then echoContent yellow "Please enter the local bandwidth peak uplink speed (default: 50, unit: Mbps)" initRealityClientServersName initRealityKey echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Xray to start automatically at boot" echo mapfile -t result < <(initSingBoxPort "${singBoxVLESSRealityGRPCPort}") echoContent green " ---> Xray closed successfully" cat </etc/v2ray-agent/sing-box/conf/config/08_VLESS_vision_gRPC_inbounds.json { "inbounds": [ { "type": "vless", "listen":"::", "listen_port":${result[-1]}, "users":$(initSingBoxClients 8), "tag": "VLESSRealityGRPC", "tls": { "enabled": true, "server_name": "${realityServerName}", "reality": { "enabled": true, "handshake":{ "server":"${realityServerName}", "server_port":${realityDomainPort} }, "private_key": "${realityPrivateKey}", "short_id": [ "", "6ba85179e30d4fc2" ] } }, "transport": { "type": "grpc", "service_name": "grpc" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/08_VLESS_vision_gRPC_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",6," || [[ "$1" == "all" ]]; then echoContent yellow "\n ---> Upload speed: ${hysteriaClientUploadSpeed}\n" echoContent skyBlue "\nPlease select the protocol type" echo mapfile -t result < <(initSingBoxPort "${singBoxHysteria2Port}") echoContent green "\nPort range: ${hysteriaPortHoppingRange}\n" initHysteria2Network cat </etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json { "inbounds": [ { "type": "hysteria2", "listen": "::", "listen_port": ${result[-1]}, "users": $(initSingBoxClients 6), "up_mbps":${hysteria2ClientDownloadSpeed}, "down_mbps":${hysteria2ClientUploadSpeed}, "tls": { "enabled": true, "server_name":"${sslDomain}", "alpn": [ "h3" ], "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",4," || [[ "$1" == "all" ]]; then echoContent yellow "# Notes\n" echoContent skyBlue "\nProgress 1/1: Port jump" echo mapfile -t result < <(initSingBoxPort "${singBoxTrojanPort}") echoContent green " ---> Port hopping added successfully" cat </etc/v2ray-agent/sing-box/conf/config/04_trojan_TCP_inbounds.json { "inbounds": [ { "type": "trojan", "listen": "::", "listen_port": ${result[-1]}, "users": $(initSingBoxClients 4), "tls": { "enabled": true, "server_name":"${sslDomain}", "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/04_trojan_TCP_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",9," || [[ "$1" == "all" ]]; then echoContent yellow "Only supports UDP" echoContent skyBlue "\nProgress 1/1: Port jump" echo mapfile -t result < <(initSingBoxPort "${singBoxTuicPort}") echoContent green " ---> Deletion successful" initTuicProtocol cat </etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json { "inbounds": [ { "type": "tuic", "listen": "::", "tag": "singbox-tuic-in", "listen_port": ${result[-1]}, "users": $(initSingBoxClients 9), "congestion_control": "${tuicAlgorithm}", "tls": { "enabled": true, "server_name":"${sslDomain}", "alpn": [ "h3" ], "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",10," || [[ "$1" == "all" ]]; then echoContent yellow "The starting position of port jumping is 30000" echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Hysteria configuration" echo mapfile -t result < <(initSingBoxPort "${singBoxNaivePort}") echoContent green " ---> The current port hopping range is: ${portHoppingStart}-${portHoppingEnd}" cat </etc/v2ray-agent/sing-box/conf/config/10_naive_inbounds.json { "inbounds": [ { "type": "naive", "listen": "::", "tag": "singbox-naive-in", "listen_port": ${result[-1]}, "users": $(initSingBoxClients 10), "tls": { "enabled": true, "server_name":"${sslDomain}", "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/10_naive_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",11," || [[ "$1" == "all" ]]; then echoContent yellow "The end position of port jumping is 60000" echoContent skyBlue "\nPlease select the algorithm type" echo mapfile -t result < <(initSingBoxPort "${singBoxVMessHTTPUpgradePort}") echoContent green "\n ---> Port: ${tuicPort}" checkDNSIP "${domain}" removeNginxDefaultConf handleSingBox stop randomPathFunction rm -rf "${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf" >/dev/null 2>&1 checkPortOpen "${result[-1]}" "${domain}" singBoxNginxConfig "$1" "${result[-1]}" bootStartup nginx cat </etc/v2ray-agent/sing-box/conf/config/11_VMess_HTTPUpgrade_inbounds.json { "inbounds":[ { "type": "vmess", "listen":"127.0.0.1", "listen_port":31306, "tag":"VMessHTTPUpgrade", "users":$(initSingBoxClients 11), "transport": { "type": "httpupgrade", "path": "/${currentPath}" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/11_VMess_HTTPUpgrade_inbounds.json >/dev/null 2>&1 fi if echo "${selectCustomInstallType}" | grep -q ",13," || [[ "$1" == "all" ]]; then echoContent yellow "You can choose a segment in the range of 30000-60000" echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Tuic configuration" echo mapfile -t result < <(initSingBoxPort "${singBoxAnyTLSPort}") echoContent green "\n ---> Used successfully" cat </etc/v2ray-agent/sing-box/conf/config/13_anytls_inbounds.json { "inbounds": [ { "type": "anytls", "listen": "::", "tag":"anytls", "listen_port": ${result[-1]}, "users": $(initSingBoxClients 13), "tls": { "enabled": true, "server_name":"${sslDomain}", "certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt", "key_path": "/etc/v2ray-agent/tls/${sslDomain}.key" } } ] } EOF elif [[ -z "$3" ]]; then rm /etc/v2ray-agent/sing-box/conf/config/13_anytls_inbounds.json >/dev/null 2>&1 fi if [[ -z "$3" ]]; then removeSingBoxConfig wireguard_endpoints_IPv4_route removeSingBoxConfig wireguard_endpoints_IPv6_route removeSingBoxConfig wireguard_endpoints_IPv4 removeSingBoxConfig wireguard_endpoints_IPv6 removeSingBoxConfig IPv4_out removeSingBoxConfig IPv6_out removeSingBoxConfig IPv6_route removeSingBoxConfig block removeSingBoxConfig cn_block_outbound removeSingBoxConfig cn_block_route removeSingBoxConfig 01_direct_outbound removeSingBoxConfig socks5_outbound.json removeSingBoxConfig block_domain_outbound removeSingBoxConfig dns fi setSniffRouting } initSubscribeLocalConfig() { rm -rf /etc/v2ray-agent/subscribe_local/sing-box/* } # General defaultBase64Code() { local type=$1 local port=$2 local email=$3 local id=$4 local add=$5 local path=$6 local user= user=$(echo "${email}" | awk -F "[-]" '{print $1}') if [[ ! -f "/etc/v2ray-agent/subscribe_local/sing-box/${user}" ]]; then echo [] >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" fi local singBoxSubscribeLocalConfig= if [[ "${type}" == "vlesstcp" ]]; then echoContent yellow "Recommend about 1000" echoContent green " vless://${id}@${currentHost}:${port}?encryption=none&security=tls&fp=chrome&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\n" echoContent yellow "Please enter the port jumping range, for example [30000-31000]" echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=tls&fp=chrome&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx- vision#${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vless://${id}@${currentHost}:${port}?encryption=none&security=tls&type=tcp&host=${currentHost}&fp=chrome&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vless server: ${currentHost} port: ${port} uuid: ${id} network: tcp tls: true udp: true flow: xtls-rprx-vision client-fingerprint: chrome EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"${currentHost}\",\"server_port\":${port},\"uuid\":\"${id}\",\"flow\":\"xtls-rprx-vision\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"packet_encoding\":\"xudp\"}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "1.Add port hopping" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${currentHost}%3A${port}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\n" elif [[ "${type}" == "vmessws" ]]; then qrCodeBase64Default=$(echo -n "{\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"ws\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}" | base64 -w 0) qrCodeBase64Default="${qrCodeBase64Default// /}" echoContent yellow "2.Delete port hopping" echoContent green " {\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"ws\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}\n" echoContent yellow "3.Check port jumping" echoContent green " vmess://${qrCodeBase64Default}\n" echoContent yellow "\n ---> Port: ${tuicPort}" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vmess://${qrCodeBase64Default} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vmess server: ${add} port: ${port} uuid: ${id} alterId: 0 cipher: none udp: true tls: true client-fingerprint: chrome servername: ${currentHost} network: ws ws-opts: path: ${path} headers: Host: ${currentHost} EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vmess\",\"server\":\"${add}\",\"server_port\":${port},\"uuid\":\"${id}\",\"alter_id\":0,\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"packet_encoding\":\"packetaddr\",\"transport\":{\"type\":\"ws\",\"path\":\"${path}\",\"max_early_data\":2048,\"early_data_header_name\":\"Sec-WebSocket-Protocol\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n" elif [[ "${type}" == "vlessws" ]]; then echoContent yellow "Please enter the Tuic port [enter random 10000-30000], cannot be repeated with other services" echoContent green " vless://${id}@${add}:${port}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=${path}#${email}\n" echoContent yellow "1.bbr(default)" echoContent green "Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, client-fingerprint: chrome, transmission method: tcp, flow: xtls-rprx -vision, account name:${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vless://${id}@${add}:${port}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=${path}#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vless server: ${add} port: ${port} uuid: ${id} udp: true tls: true network: ws client-fingerprint: chrome servername: ${currentHost} ws-opts: path: ${path} headers: Host: ${currentHost} EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"${add}\",\"server_port\":${port},\"uuid\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"multiplex\":{\"enabled\":false,\"protocol\":\"smux\",\"max_streams\":32},\"packet_encoding\":\"xudp\",\"transport\":{\"type\":\"ws\",\"path\":\"${path}\",\"headers\":{\"Host\":\"${currentHost}\"}}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "2.cubic" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dws%26host%3D${currentHost}%26fp%3Dchrome%26sni%3D${currentHost}%26path%3D${path}%23${email}" elif [[ "${type}" == "vlessXHTTP" ]]; then local xhttpMldsa65Param= local xhttpMldsa65ParamEncoded= if [[ -n "${currentRealityMldsa65Verify}" && "${currentRealityMldsa65Verify}" != "null" ]]; then xhttpMldsa65Param="&pqv=${currentRealityMldsa65Verify}" xhttpMldsa65ParamEncoded="%26pqv%3D${currentRealityMldsa65Verify}" fi echoContent yellow "3.new_reno" echoContent green " vless://${id}@${add}:${port}?encryption=none&security=reality${xhttpMldsa65Param}&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&host=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email}\n" echoContent yellow "\n ---> Algorithm: ${tuicAlgorithm}\n" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${currentHost}%3A${currentDefaultPort}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vless://${id}@${add}:${port}?encryption=none&security=reality${xhttpMldsa65Param}&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vless server: ${add} port: ${port} uuid: ${id} udp: true tls: true network: xhttp client-fingerprint: chrome alpn: - h2 servername: ${xrayVLESSRealityXHTTPServerName} xhttp-opts: path: ${path} host: ${xrayVLESSRealityXHTTPServerName} reality-opts: public-key: ${currentRealityXHTTPPublicKey} short-id: 6ba85179e30d4fc2 EOF echoContent yellow "# Notes\n" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dreality${xhttpMldsa65ParamEncoded}%26type%3Dxhttp%26sni%3D${xrayVLESSRealityXHTTPServerName}%26fp%3Dchrome%26path%3D${path}%26host%3D${xrayVLESSRealityXHTTPServerName}%26pbk%3D${currentRealityXHTTPPublicKey}%26sid%3D6ba85179e30d4fc2%23${email}\n" elif [[ "${type}" == "vlessgrpc" ]] then echoContent yellow "will replace the prefix with ${xtlsType}" echoContent green " vless://${id}@${add}:${port}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&fp=chrome&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}\n" echoContent yellow "If the prefix is Trojan, two Trojan protocol nodes will appear when viewing the account, and one of them is unavailable xtls" echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&fp=chrome&headerType=none&type=tcp#${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vless://${id}@${add}:${port}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&serviceName=${currentPath}grpc&fp=chrome&alpn=h2&sni=${currentHost}#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vless server: ${add} port: ${port} uuid: ${id} udp: true tls: true network: grpc client-fingerprint: chrome servername: ${currentHost} grpc-opts: grpc-service-name: ${currentPath}grpc EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\": \"vless\",\"server\": \"${add}\",\"server_port\": ${port},\"uuid\": \"${id}\",\"tls\": { \"enabled\": true, \"server_name\": \"${currentHost}\", \"utls\": { \"enabled\": true, \"fingerprint\": \"chrome\" }},\"packet_encoding\": \"xudp\",\"transport\": { \"type\": \"grpc\", \"service_name\": \"${currentPath}grpc\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "Execute again to switch to the last prefix\n" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dgrpc%26host%3D${currentHost}%26serviceName%3D${currentPath}grpc%26fp%3Dchrome%26path%3D${currentPath}grpc%26sni%3D${currentHost}%26alpn%3Dh2%23${email}" elif [[ "${type}" == "trojan" ]]; then # URLEncode # URLEncode echoContent yellow " ---> Trojan(TLS)" echoContent green " trojan://${id}@${currentHost}:${port}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${currentHost}_Trojan\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" trojan://${id}@${currentHost}:${port}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${email}_Trojan EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: trojan server: ${currentHost} port: ${port} password: ${id} client-fingerprint: chrome udp: true sni: ${currentHost} EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"trojan\",\"server\":\"${currentHost}\",\"server_port\":${port},\"password\":\"${id}\",\"tls\":{\"alpn\":[\"http/1.1\"],\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "1.Switch to ${xtlsType}" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${currentHost}%3a${port}%3fpeer%3d${currentHost}%26fp%3Dchrome%26sni%3d${currentHost}%26alpn%3Dhttp/1.1%23${email}\n" elif [[ "${type}" == "trojangrpc" ]]; then # URLEncode # URLEncode echoContent yellow " ---> Trojan gRPC(TLS)" echoContent green " trojan://${id}@${add}:${port}?encryption=none&peer=${currentHost}&fp=chrome&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" trojan://${id}@${add}:${port}?encryption=none&peer=${currentHost}&security=tls&type=grpc&fp=chrome&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" server: ${add} port: ${port} type: trojan password: ${id} network: grpc sni: ${currentHost} udp: true grpc-opts: grpc-service-name: ${currentPath}trojangrpc EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"trojan\",\"server\":\"${add}\",\"server_port\":${port},\"password\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"insecure\":true,\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"transport\":{\"type\":\"grpc\",\"service_name\":\"${currentPath}trojangrpc\",\"idle_timeout\":\"15s\",\"ping_timeout\":\"15s\",\"permit_without_stream\":false},\"multiplex\":{\"enabled\":false,\"protocol\":\"smux\",\"max_streams\":32}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "Please enter custom UUID [need to be legal], [Enter] random UUID" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${add}%3a${port}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\n" elif [[ "${type}" == "hysteria" ]]; then echoContent yellow " ---> Hysteria(TLS)" local clashMetaPortContent="port: ${port}" local multiPort= local multiPortEncode if echo "${port}" | grep -q "-"; then clashMetaPortContent="ports: ${port}" multiPort="mport=${port}&" multiPortEncode="mport%3D${port}%26" fi echoContent green " hysteria2://${id}@${currentHost}:${singBoxHysteria2Port}?${multiPort}peer=${currentHost}&insecure=0&sni=${currentHost}&alpn=h3#${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" hysteria2://${id}@${currentHost}:${singBoxHysteria2Port}?${multiPort}peer=${currentHost}&insecure=0&sni=${currentHost}&alpn=h3#${email} EOF echoContent yellow " ---> v2rayN(hysteria+TLS)" echo "{\"server\": \"${currentHost}:${port}\",\"socks5\": { \"listen\": \"127.0.0.1:7798\", \"timeout\": 300},\"auth\":\"${id}\",\"tls\":{\"sni\":\"${currentHost}\"}}" | jq cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: hysteria2 server: ${currentHost} ${clashMetaPortContent} password: ${id} alpn: - h3 sni: ${currentHost} up: "${hysteria2ClientUploadSpeed} Mbps" down: "${hysteria2ClientDownloadSpeed} Mbps" EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"hysteria2\",\"server\":\"${currentHost}\",\"server_port\":${singBoxHysteria2Port},\"up_mbps\":${hysteria2ClientUploadSpeed},\"down_mbps\":${hysteria2ClientDownloadSpeed},\"password\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"alpn\":[\"h3\"]}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "\n ${uuid}" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria2%3A%2F%2F${id}%40${currentHost}%3A${singBoxHysteria2Port}%3F${multiPortEncode}peer%3D${currentHost}%26insecure%3D0%26sni%3D${currentHost}%26alpn%3Dh3%23${email}\n" elif [[ "${type}" == "vlessReality" ]]; then local realityServerName=${xrayVLESSRealityServerName} local publicKey=${currentRealityPublicKey} local realityMldsa65Verify=${currentRealityMldsa65Verify} if [[ "${coreInstallType}" == "2" ]]; then realityServerName=${singBoxVLESSRealityVisionServerName} publicKey=${singBoxVLESSRealityPublicKey} fi echoContent yellow "# Notes" echoContent green " vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=tcp&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\n" echoContent yellow "\nTutorial address:" echoContent green "Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, client-fingerprint: chrome, transmission method: tcp, account name: ${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=tcp&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vless server: $(getPublicIP) port: ${port} uuid: ${id} network: tcp tls: true udp: true flow: xtls-rprx-vision servername: ${realityServerName} reality-opts: public-key: ${publicKey} short-id: 6ba85179e30d4fc2 client-fingerprint: chrome EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"$(getPublicIP)\",\"server_port\":${port},\"uuid\":\"${id}\",\"flow\":\"xtls-rprx-vision\",\"tls\":{\"enabled\":true,\"server_name\":\"${realityServerName}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"},\"reality\":{\"enabled\":true,\"public_key\":\"${publicKey}\",\"short_id\":\"6ba85179e30d4fc2\"}},\"packet_encoding\":\"xudp\"}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "\n1.CNAME www.digitalocean.com" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dtcp%26sni%3D${realityServerName}%26fp%3Dchrome%26pbk%3D${publicKey}%26sid%3D6ba85179e30d4fc2%26flow%3Dxtls-rprx-vision%23${email}\n" elif [[ "${type}" == "vlessRealityGRPC" ]]; then local realityServerName=${xrayVLESSRealityServerName} local publicKey=${currentRealityPublicKey} local realityMldsa65Verify=${currentRealityMldsa65Verify} if [[ "${coreInstallType}" == "2" ]]; then realityServerName=${singBoxVLESSRealityGRPCServerName} publicKey=${singBoxVLESSRealityPublicKey} fi echoContent yellow "2.CNAME who.int" # pqv=${realityMldsa65Verify}& echoContent green " vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&type=grpc&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\n" echoContent yellow "3.CNAME blog.hostmonit.com" # pqv=${realityMldsa65Verify}, echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3a%2f%2f${id}%40${currentHost}%3a${currentDefaultPort}%3fsecurity%3dtls%26encryption%3dnone%26fp%3Dchrome%26host%3d${currentHost}%26headerType%3dnone%26type%3dtcp%23${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=grpc&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vless server: $(getPublicIP) port: ${port} uuid: ${id} network: grpc tls: true udp: true servername: ${realityServerName} reality-opts: public-key: ${publicKey} short-id: 6ba85179e30d4fc2 grpc-opts: grpc-service-name: "grpc" client-fingerprint: chrome EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"$(getPublicIP)\",\"server_port\":${port},\"uuid\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${realityServerName}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"},\"reality\":{\"enabled\":true,\"public_key\":\"${publicKey}\",\"short_id\":\"6ba85179e30d4fc2\"}},\"packet_encoding\":\"xudp\",\"transport\":{\"type\":\"grpc\",\"service_name\":\"grpc\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow "\n ---> Not used" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dgrpc%26sni%3D${realityServerName}%26fp%3Dchrome%26pbk%3D${publicKey}%26sid%3D6ba85179e30d4fc2%26path%3Dgrpc%26serviceName%3Dgrpc%23${email}\n" elif [[ "${type}" == "tuic" ]]; then local tuicUUID= tuicUUID=$(echo "${id}" | awk -F "[_]" '{print $1}') local tuicPassword= tuicPassword=$(echo "${id}" | awk -F "[_]" '{print $2}') if [[ -z "${email}" ]]; then echoContent red "\n================================================ =================" exit 0 fi echoContent yellow " ---> Universal format (VLESS+TCP+TLS_Vision)" echoContent green " trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" tuic://${tuicUUID}:${tuicPassword}@${currentHost}:${port}?congestion_control=${tuicAlgorithm}&alpn=h3&sni=${currentHost}&udp_relay_mode=quic&allow_insecure=0#${email} EOF echoContent yellow " ---> v2rayN(Tuic+TLS)" echo "{\"relay\": {\"server\": \"${currentHost}:${port}\",\"uuid\": \"${tuicUUID}\",\"password\": \"${tuicPassword}\",\"ip\": \"${currentHost}\",\"congestion_control\": \"${tuicAlgorithm}\",\"alpn\": [\"h3\"]},\"local\": {\"server\": \"127.0.0.1:7798\"},\"log_level\": \"warn\"}" | jq cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" server: ${currentHost} type: tuic port: ${port} uuid: ${tuicUUID} password: ${tuicPassword} alpn: - h3 congestion-controller: ${tuicAlgorithm} disable-sni: true reduce-rtt: true sni: ${email} EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\": \"tuic\",\"server\": \"${currentHost}\",\"server_port\": ${port},\"uuid\": \"${tuicUUID}\",\"password\": \"${tuicPassword}\",\"congestion_control\": \"${tuicAlgorithm}\",\"tls\": {\"enabled\": true,\"server_name\": \"${currentHost}\",\"alpn\": [\"h3\"]}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow " ---> Formatted plain text (VLESS+TCP+TLS_Vision)" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=tuic%3A%2F%2F${tuicUUID}%3A${tuicPassword}%40${currentHost}%3A${tuicPort}%3Fcongestion_control%3D${tuicAlgorithm}%26alpn%3Dh3%26sni%3D${currentHost}%26udp_relay_mode%3Dquic%26allow_insecure%3D0%23${email}\n" elif [[ "${type}" == "naive" ]]; then echoContent yellow " ---> Naive(TLS)" echoContent green " naive+https://${email}:${id}@${currentHost}:${port}?padding=true#${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" naive+https://${email}:${id}@${currentHost}:${port}?padding=true#${email} EOF echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS_Vision)" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=naive%2Bhttps%3A%2F%2F${email}%3A${id}%40${currentHost}%3A${port}%3Fpadding%3Dtrue%23${email}\n" elif [[ "${type}" == "vmessHTTPUpgrade" ]]; then qrCodeBase64Default=$(echo -n "{\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"httpupgrade\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}" | base64 -w 0) qrCodeBase64Default="${qrCodeBase64Default// /}" echoContent yellow " ---> Universal format (VLESS+TCP+TLS)" echoContent green " {\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"httpupgrade\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}\n" echoContent yellow " ---> Formatted plain text (VLESS+TCP+TLS)" echoContent green " vmess://${qrCodeBase64Default}\n" echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS)" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" vmess://${qrCodeBase64Default} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: vmess server: ${add} port: ${port} uuid: ${id} alterId: 0 cipher: auto udp: true tls: true client-fingerprint: chrome servername: ${currentHost} network: ws ws-opts: path: ${path} headers: Host: ${currentHost} v2ray-http-upgrade: true EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vmess\",\"server\":\"${add}\",\"server_port\":${port},\"uuid\":\"${id}\",\"security\":\"auto\",\"alter_id\":0,\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"packet_encoding\":\"packetaddr\",\"transport\":{\"type\":\"httpupgrade\",\"path\":\"${path}\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n" elif [[ "${type}" == "anytls" ]]; then echoContent yellow " ---> AnyTLS" echoContent yellow " ---> Common format (Trojan+TCP+TLS_Vision)" echoContent green "Protocol type: Trojan, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: xtls, transmission method: tcp, flow: xtls-rprx-vision, account name: ${email}\n" echoContent green " anytls://${id}@${currentHost}:${singBoxAnyTLSPort}?peer=${currentHost}&insecure=0&sni=${currentHost}#${email}\n" cat <>"/etc/v2ray-agent/subscribe_local/default/${user}" anytls://${id}@${currentHost}:${singBoxAnyTLSPort}?peer=${currentHost}&insecure=0&sni=${currentHost}#${email} EOF cat <>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}" - name: "${email}" type: anytls port: ${singBoxAnyTLSPort} server: ${currentHost} password: ${id} client-fingerprint: chrome udp: true sni: ${currentHost} alpn: - h2 - http/1.1 EOF singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"anytls\",\"server\":\"${currentHost}\",\"server_port\":${singBoxAnyTLSPort},\"password\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}") echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}" echoContent yellow " ---> Formatted plain text (Trojan+TCP+TLS_Vision)" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=anytls%3A%2F%2F${id}%40${currentHost}%3A${singBoxAnyTLSPort}%3Fpeer%3D${currentHost}%26insecure%3D0%26sni%3D${currentHost}%23${email}\n" fi } # Get Reality subscription port getRealitySubscriptionPort() { local protocol=$1 if [[ "${coreInstallType}" == "2" ]]; then if [[ "${protocol}" == "grpc" ]]; then printf '%s\n' "${singBoxVLESSRealityGRPCPort}" else printf '%s\n' "${singBoxVLESSRealityVisionPort}" fi else printf '%s\n' "${xrayVLESSRealityVisionPort}" fi } # account showAccounts() { readInstallType readInstallProtocolType readConfigHostPathUUID readSingBoxConfig echo echoContent skyBlue "\nProgress$2/${totalProgress}: Initializing V2Ray configuration" initSubscribeLocalConfig # VLESS TCP if echo ${currentInstallProtocolType} | grep -q ",0,"; then echoContent skyBlue "\nFunction 1/${totalProgress}: Switch to ${xtlsType}" jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}02_VLESS_TCP_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) echoContent skyBlue "\nProgress$2/${totalProgress}: Initializing Xray configuration" echo defaultBase64Code vlesstcp "${currentDefaultPort}${singBoxVLESSVisionPort}" "${email}" "$(echo "${user}" | jq -r .id//.uuid)" done fi # VLESS WS if echo ${currentInstallProtocolType} | grep -q ",1,"; then echoContent skyBlue "\n===================== Configure VLESS+Reality ==================== =\n" jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}03_VLESS_WS_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) local vlessWSPort=${currentDefaultPort} if [[ "${coreInstallType}" == "2" ]]; then vlessWSPort="${singBoxVLESSWSPort}" fi echo local path="${currentPath}ws" if [[ ${coreInstallType} == "1" ]]; then path="/${currentPath}ws" elif [[ "${coreInstallType}" == "2" ]]; then path="${singBoxVLESSWSPath}" fi local count= while read -r line; do echoContent skyBlue "\nProgress$1/${totalProgress}: Add cloudflare custom CNAME" if [[ -n "${line}" ]]; then defaultBase64Code vlessws "${vlessWSPort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}" count=$((count + 1)) echo fi done < <(echo "${currentCDNAddress}" | tr ',' '\n') done fi # trojan grpc if echo ${currentInstallProtocolType} | grep -q ",2,"; then echoContent skyBlue "https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip" jq .inbounds[0].settings.clients ${configPath}04_trojan_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email) local count= while read -r line; do echoContent skyBlue "----------------------------" echo if [[ -n "${line}" ]]; then defaultBase64Code trojangrpc "${currentDefaultPort}" "${email}${count}" "$(echo "${user}" | jq -r .password)" "${line}" count=$((count + 1)) fi done < <(echo "${currentCDNAddress}" | tr ',' '\n') done fi # VMess WS if echo ${currentInstallProtocolType} | grep -q ",3,"; then echoContent skyBlue "\nProgress$1/${totalProgress}: account" local path="${currentPath}vws" if [[ ${coreInstallType} == "1" ]]; then path="/${currentPath}vws" elif [[ "${coreInstallType}" == "2" ]]; then path="${singBoxVMessWSPath}" fi jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}05_VMess_WS_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) local vmessPort=${currentDefaultPort} if [[ "${coreInstallType}" == "2" ]]; then vmessPort="${singBoxVMessWSPort}" fi local count= while read -r line; do echoContent skyBlue "===================== Trojan TCP TLS_Vision ======================\n" echo if [[ -n "${line}" ]]; then defaultBase64Code vmessws "${vmessPort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}" count=$((count + 1)) fi done < <(echo "${currentCDNAddress}" | tr ',' '\n') done fi # trojan tcp if echo ${currentInstallProtocolType} | grep -q ",4,"; then echoContent skyBlue "\n --->Account:${email}" jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}04_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) echoContent skyBlue "============================= VLESS TCP TLS_Vision ==============================\n" defaultBase64Code trojan "${currentDefaultPort}${singBoxTrojanPort}" "${email}" "$(echo "${user}" | jq -r .password)" done fi # VLESS grpc if echo ${currentInstallProtocolType} | grep -q ",5,"; then echoContent skyBlue "\n --->Account:${email}" jq .inbounds[0].settings.clients ${configPath}06_VLESS_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email) local count= while read -r line; do echoContent skyBlue "\n================================ VLESS WS TLS CDN ================================\n" echo if [[ -n "${line}" ]]; then defaultBase64Code vlessgrpc "${currentDefaultPort}" "${email}${count}" "$(echo "${user}" | jq -r .id)" "${line}" count=$((count + 1)) fi done < <(echo "${currentCDNAddress}" | tr ',' '\n') done fi # hysteria2 if echo ${currentInstallProtocolType} | grep -q ",6," || [[ -n "${hysteriaPort}" ]]; then readPortHopping "hysteria2" "${singBoxHysteria2Port}" echoContent skyBlue "\n --->Account:${email}" local path="${configPath}" if [[ "${coreInstallType}" == "1" ]]; then path="${singBoxConfigPath}" fi local hysteria2DefaultPort= if [[ -n "${hysteria2PortHoppingStart}" && -n "${hysteria2PortHoppingEnd}" ]]; then hysteria2DefaultPort="${hysteria2PortHopping}" else hysteria2DefaultPort=${singBoxHysteria2Port} fi jq -r -c '.inbounds[]|.users[]' "${path}06_hysteria2_inbounds.json" | while read -r user; do echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .name)" echo defaultBase64Code hysteria "${hysteria2DefaultPort}" "$(echo "${user}" | jq -r .name)" "$(echo "${user}" | jq -r .password)" done fi # VLESS reality vision if echo ${currentInstallProtocolType} | grep -q ",7,"; then echoContent skyBlue "\n=============================== VLESS gRPC TLS CDN ===============================\n" jq .inbounds[1].settings.clients//.inbounds[0].users ${configPath}07_VLESS_vision_reality_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) echoContent skyBlue "\n --->Account:${email}" echo defaultBase64Code vlessReality "$(getRealitySubscriptionPort vision)" "${email}" "$(echo "${user}" | jq -r .id//.uuid)" done fi # VLESS reality gRPC if echo ${currentInstallProtocolType} | grep -q ",8,"; then echoContent skyBlue "\n================================ VMess WS TLS CDN ================================\n" jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}08_VLESS_vision_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) echoContent skyBlue "\n --->Account:${email}" echo defaultBase64Code vlessRealityGRPC "$(getRealitySubscriptionPort grpc)" "${email}" "$(echo "${user}" | jq -r .id//.uuid)" done fi # tuic if echo ${currentInstallProtocolType} | grep -q ",9," || [[ -n "${tuicPort}" ]]; then echoContent skyBlue "\n================================== Trojan TLS ==================================\n" local path="${configPath}" if [[ "${coreInstallType}" == "1" ]]; then path="${singBoxConfigPath}" fi jq -r -c '.inbounds[].users[]' "${path}09_tuic_inbounds.json" | while read -r user; do echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .name)" echo defaultBase64Code tuic "${singBoxTuicPort}" "$(echo "${user}" | jq -r .name)" "$(echo "${user}" | jq -r .uuid)_$(echo "${user}" | jq -r .password)" done fi # naive if echo ${currentInstallProtocolType} | grep -q ",10," || [[ -n "${singBoxNaivePort}" ]]; then echoContent skyBlue "\n --->Account:${email}" jq -r -c '.inbounds[]|.users[]' "${configPath}10_naive_inbounds.json" | while read -r user; do echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .username)" echo defaultBase64Code naive "${singBoxNaivePort}" "$(echo "${user}" | jq -r .username)" "$(echo "${user}" | jq -r .password)" done fi # VMess HTTPUpgrade if echo ${currentInstallProtocolType} | grep -q ",11,"; then echoContent skyBlue "\n================================ Trojan gRPC TLS ================================\n" local path="${currentPath}vws" if [[ ${coreInstallType} == "1" ]]; then path="/${currentPath}vws" elif [[ "${coreInstallType}" == "2" ]]; then path="${singBoxVMessHTTPUpgradePath}" fi jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}11_VMess_HTTPUpgrade_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) local vmessHTTPUpgradePort=${currentDefaultPort} if [[ "${coreInstallType}" == "2" ]]; then vmessHTTPUpgradePort="${singBoxVMessHTTPUpgradePort}" fi local count= while read -r line; do echoContent skyBlue "\n --->Account:${email}" echo if [[ -n "${line}" ]]; then defaultBase64Code vmessHTTPUpgrade "${vmessHTTPUpgradePort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}" count=$((count + 1)) fi done < <(echo "${currentCDNAddress}" | tr ',' '\n') done fi # VLESS Reality XHTTP if echo ${currentInstallProtocolType} | grep -q ",12,"; then echoContent skyBlue "\n================================ Hysteria TLS ================================\n" jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}12_VLESS_XHTTP_inbounds.json | jq -c '.[]' | while read -r user; do local email= email=$(echo "${user}" | jq -r .email//.name) echo local path="${currentPath}xHTTP" local count= while read -r line; do echoContent skyBlue "============================= VLESS reality_vision ==============================\n" if [[ -z "${line}" ]]; then line=$(getPublicIP) fi if [[ -n "${line}" ]]; then defaultBase64Code vlessXHTTP "${xrayVLESSRealityXHTTPort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}" count=$((count + 1)) echo fi done < <(echo "${currentCDNAddress}" | tr ',' '\n') done fi # AnyTLS if echo ${currentInstallProtocolType} | grep -q ",13,"; then echoContent skyBlue "\n================================ AnyTLS ================================\n" jq -r -c '.inbounds[]|.users[]' "${configPath}13_anytls_inbounds.json" | while read -r user; do echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .name)" echo defaultBase64Code anytls "${singBoxAnyTLSPort}" "$(echo "${user}" | jq -r .name)" "$(echo "${user}" | jq -r .password)" done fi } # Remove nginx302 configuration removeNginx302() { local count= grep -n "return 302" <"${nginxConfigPath}alone.conf" | while read -r line; do if ! echo "${line}" | grep -q "request_uri"; then local removeIndex= removeIndex=$(echo "${line}" | awk -F "[:]" '{print $1}') removeIndex=$((removeIndex + count)) sed -i "${removeIndex}d" ${nginxConfigPath}alone.conf count=$((count - 1)) fi done } # Check if 302 is successful checkNginx302() { local domain302Status= domain302Status=$(curl -s "https://${currentHost}:${currentPort}") if echo "${domain302Status}" | grep -q "302"; then # local domain302Result= # domain302Result=$(curl -L -s "https://${currentHost}:${currentPort}") # if [[ -n "${domain302Result}" ]]; then echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3A%2F%2F${id}%40${currentHost}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dxtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\n" exit 0 # fi fi echoContent red " ---> Range cannot be empty" backupNginxConfig restoreBackup } # Backup and restore nginx files backupNginxConfig() { if [[ "$1" == "backup" ]]; then cp ${nginxConfigPath}alone.conf /etc/v2ray-agent/alone_backup.conf echoContent green " {\"port\":${currentDefaultPort},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"/${currentPath}vws\",\"net\":\"ws\",\"add\":\"${add}\",\"allowInsecure\":0,\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}\n" fi if [[ "$1" == "restoreBackup" ]] && [[ -f "/etc/v2ray-agent/alone_backup.conf" ]]; then cp /etc/v2ray-agent/alone_backup.conf ${nginxConfigPath}alone.conf echoContent green " vmess://${qrCodeBase64Default}\n" rm /etc/v2ray-agent/alone_backup.conf fi } # Add 302 configuration addNginx302() { # local line302Result= # line302Result=$(| tail -n 1) local count=1 grep -n "location / {" <"${nginxConfigPath}alone.conf" | while read -r line; do if [[ -n "${line}" ]]; then local insertIndex= insertIndex="$(echo "${line}" | awk -F "[:]" '{print $1}')" insertIndex=$((insertIndex + count)) sed "${insertIndex}i return 302 '$1';" ${nginxConfigPath}alone.conf >${nginxConfigPath}tmpfile && mv ${nginxConfigPath}tmpfile ${nginxConfigPath}alone.conf count=$((count + 1)) else echoContent red " ---> The range is illegal" backupNginxConfig restoreBackup fi done } # Update camouflage station updateNginxBlog() { if [[ "${coreInstallType}" == "2" ]]; then echoContent red " ---> The range is illegal" exit 0 fi echoContent skyBlue "\n --->Account:${email}" if ! echo "${currentInstallProtocolType}" | grep -q ",0," || [[ -z "${coreInstallType}" ]]; then echoContent red " ---> Failed to add port hopping" exit 0 fi echoContent red "==============================================================" echoContent yellow " ---> QR code Trojan(Trojan+TCP+TLS_Vision)" echoContent yellow " ---> Universal json(VMess+WS+TLS)" echoContent yellow " ---> Universal vmess (VMess+WS+TLS) link" echoContent yellow " ---> QR code vmess(VMess+WS+TLS)" echoContent yellow " ---> Universal format (VLESS+WS+TLS)" echoContent yellow " ---> Formatted plain text (VLESS+WS+TLS)" echoContent yellow "6.mikutap[https://github.com/HFIProgramming/mikutap]" echoContent yellow " ---> QR code VLESS(VLESS+WS+TLS)" echoContent yellow " ---> Universal format (VLESS+gRPC+TLS)" echoContent yellow " ---> Formatted plain text (VLESS+gRPC+TLS)" echoContent yellow " ---> QR code VLESS(VLESS+gRPC+TLS)" echoContent red "==============================================================" read -r -p "Please select:" selectInstallNginxBlogType if [[ "${selectInstallNginxBlogType}" == "10" ]]; then if [[ "${coreInstallType}" == "2" ]]; then echoContent red " ---> Unable to recognize iptables tool, unable to use port jump, exit installation" exit 0 fi echoContent red "\n==============================================================" echoContent yellow " ---> Trojan(TLS)" echoContent yellow " ---> QR code Trojan(TLS)" echoContent yellow " ---> Trojan gRPC(TLS)" echoContent yellow " ---> QR code Trojan gRPC(TLS)" echoContent red "==============================================================" read -r -p "Please select:" redirectStatus if [[ "${redirectStatus}" == "1" ]]; then backupNginxConfig backup read -r -p "Please enter the domain name to be redirected, for example https://www.baidu.com:" redirectDomain removeNginx302 addNginx302 "${redirectDomain}" handleNginx stop handleNginx start if [[ -z $(pgrep -f "nginx") ]]; then backupNginxConfig restoreBackup handleNginx start exit 0 fi checkNginx302 exit 0 fi if [[ "${redirectStatus}" == "2" ]]; then removeNginx302 echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n" exit 0 fi fi if [[ "${selectInstallNginxBlogType}" =~ ^[1-9]$ ]]; then rm -rf "${nginxStaticPath}*" if [[ "${release}" == "alpine" ]]; then wget -q -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip" else wget -q "${wgetShowProgressStatus}" -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip" fi unzip -o "${nginxStaticPath}html${selectInstallNginxBlogType}.zip" -d "${nginxStaticPath}" >/dev/null rm -f "${nginxStaticPath}html${selectInstallNginxBlogType}.zip*" echoContent green " vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=/${currentPath}ws #${email}\n" else echoContent red "\n================================================ =================" updateNginxBlog fi } #Add new port addCorePort() { if [[ "${coreInstallType}" == "2" ]]; then echoContent red " ---> Port cannot be empty" exit 0 fi echoContent skyBlue "============================== VLESS reality_gRPC ===============================\n" echoContent red "\n==============================================================" echoContent yellow " ---> Hysteria(TLS)" echoContent yellow " ---> v2rayN(hysteria+TLS)" echoContent yellow " ---> QR code Hysteria(TLS)" echoContent yellow " ---> Universal format (VLESS+reality+uTLS+Vision)" echoContent yellow " ---> Formatted plain text (VLESS+reality+uTLS+Vision)" echoContent yellow " ---> QR code VLESS(VLESS+reality+uTLS+Vision)" echoContent yellow " ---> Universal format (VLESS+reality+uTLS+gRPC)" echoContent yellow " ---> Formatted plain text (VLESS+reality+uTLS+gRPC)" echoContent yellow " ---> QR code VLESS(VLESS+reality+uTLS+gRPC)" echoContent yellow " ---> Formatted plain text (Tuic+TLS)" echoContent red "==============================================================" read -r -p "Please select:" selectNewPortType if [[ "${selectNewPortType}" == "1" ]]; then find ${configPath} -name "*dokodemodoor*" | grep -v "hysteria" | awk -F "[c][o][n][f][/]" '{print $2}' | awk -F "[_]" '{print $4}' | awk -F "[.]" '{print ""NR""":"$1}' exit 0 elif [[ "${selectNewPortType}" == "2" ]]; then read -r -p "Please enter the port number:" newPort read -r -p "Please enter the default port number. The subscription port and node port will be changed at the same time. [Enter] Default 443:" defaultPort if [[ -n "${defaultPort}" ]]; then rm -rf "$(find ${configPath}* | grep "default")" fi if [[ -n "${newPort}" ]]; then while read -r port; do rm -rf "$(find ${configPath}* | grep "${port}")" local fileName= local hysteriaFileName= if [[ -n "${defaultPort}" && "${port}" == "${defaultPort}" ]]; then fileName="${configPath}02_dokodemodoor_inbounds_${port}_default.json" else fileName="${configPath}02_dokodemodoor_inbounds_${port}.json" fi if [[ -n ${hysteriaPort} ]]; then hysteriaFileName="${configPath}02_dokodemodoor_inbounds_hysteria_${port}.json" fi allowPort "${port}" allowPort "${port}" "udp" local settingsPort=443 if [[ -n "${customPort}" ]]; then settingsPort=${customPort} fi if [[ -n ${hysteriaFileName} ]]; then cat <"${hysteriaFileName}" { "inbounds": [ { "listen": "0.0.0.0", "port": ${port}, "protocol": "dokodemo-door", "settings": { "address": "127.0.0.1", "port": ${hysteriaPort}, "network": "udp", "followRedirect": false }, "tag": "dokodemo-door-newPort-hysteria-${port}" } ] } EOF fi cat <"${fileName}" { "inbounds": [ { "listen": "0.0.0.0", "port": ${port}, "protocol": "dokodemo-door", "settings": { "address": "127.0.0.1", "port": ${settingsPort}, "network": "tcp", "followRedirect": false }, "tag": "dokodemo-door-newPort-${port}" } ] } EOF done < <(echo "${newPort}" | tr ',' '\n') echoContent green "Protocol type: VLESS, address: ${add}, disguised domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, client-fingerprint: chrome, user ID: ${id}, security: tls, Transmission method: ws, path: /${currentPath}ws, account name: ${email}\n" reloadCore addCorePort fi elif [[ "${selectNewPortType}" == "3" ]]; then find ${configPath} -name "*dokodemodoor*" | grep -v "hysteria" | awk -F "[c][o][n][f][/]" '{print $2}' | awk -F "[_]" '{print $4}' | awk -F "[.]" '{print ""NR""":"$1}' read -r -p "Please enter the port number to be deleted:" portIndex local dokoConfig dokoConfig=$(find ${configPath} -name "*dokodemodoor*" | grep -v "hysteria" | awk -F "[c][o][n][f][/]" '{print $2}' | awk -F "[_]" '{print $4}' | awk -F "[.]" '{print ""NR""":"$1}' | grep "${portIndex}:") if [[ -n "${dokoConfig}" ]]; then rm "${configPath}02_dokodemodoor_inbounds_$(echo "${dokoConfig}" | awk -F "[:]" '{print $2}').json" local hysteriaDokodemodoorFilePath= hysteriaDokodemodoorFilePath="${configPath}02_dokodemodoor_inbounds_hysteria_$(echo "${dokoConfig}" | awk -F "[:]" '{print $2}').json" if [[ -f "${hysteriaDokodemodoorFilePath}" ]]; then rm "${hysteriaDokodemodoorFilePath}" fi reloadCore addCorePort else echoContent yellow " ---> v2rayN(Tuic+TLS)" addCorePort fi fi } # Uninstall script unInstall() { read -r -p "Are you sure you want to uninstall the installation content? [y/n]:" unInstallStatus if [[ "${unInstallStatus}" != "y" ]]; then echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dws%26host%3D${currentHost}%26fp%3Dchrome%26sni%3D${currentHost}%26path%3D%252f${currentPath}ws%23${email}" menu exit 0 fi # checkBTPanel echoContent yellow "\n --->Tuic will be warmer and may have a smoother user experience than Hysteria." handleNginx stop if [[ -z $(pgrep -f "nginx") ]]; then echoContent green " vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&fp=chrome&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}\n" fi if [[ "${release}" == "alpine" ]]; then if [[ "${coreInstallType}" == "1" ]]; then handleXray stop rc-update del xray default rm -rf /etc/init.d/xray echoContent green "Protocol type: VLESS, address: ${add}, disguised domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, transmission method: gRPC, alpn :h2, client-fingerprint: chrome, serviceName: ${currentPath}grpc, account name: ${email}\n" fi if [[ "${coreInstallType}" == "2" || -n "${singBoxConfigPath}" ]]; then handleSingBox stop rc-update del sing-box default rm -rf /etc/init.d/sing-box echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dgrpc%26host%3D${currentHost}%26serviceName%3D${currentPath}grpc%26fp%3Dchrome%26path%3D${currentPath}grpc%26sni%3D${currentHost}%26alpn%3Dh2%23${email}" fi else if [[ "${coreInstallType}" == "1" ]]; then handleXray stop rm -rf /etc/systemd/system/xray.service echoContent green " trojan://${id}@${currentHost}:${currentDefaultPort}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${currentHost}_Trojan\n" fi if [[ "${coreInstallType}" == "2" || -n "${singBoxConfigPath}" ]]; then handleSingBox stop rm -rf /etc/systemd/system/sing-box.service echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${currentHost}%3a${port}%3fpeer%3d${currentHost}%26fp%3Dchrome%26sni%3d${currentHost}%26alpn%3Dhttp/1.1%23${email}\n" fi fi # if [[ -f "/root/.acme.sh/acme.sh.env" ]] && grep -q 'acme.sh.env' Backup certificate successful, please save it. [/tmp/v2ray-agent-tls]" #fi #fi rm -rf /etc/v2ray-agent rm -rf ${nginxConfigPath}alone.conf rm -rf ${nginxConfigPath}checkPortOpen.conf >/dev/null 2>&1 rm -rf "${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf" >/dev/null 2>&1 rm -rf ${nginxConfigPath}checkPortOpen.conf >/dev/null 2>&1 unInstallSubscribe if [[ -d "${nginxStaticPath}" && -f "${nginxStaticPath}/check" ]]; then rm -rf "${nginxStaticPath}" echoContent green " trojan://${id}@${add}:${currentDefaultPort}?encryption=none&peer=${currentHost}&fp=chrome&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\n" fi rm -rf /usr/bin/vasma rm -rf /usr/sbin/vasma echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${add}%3a${currentDefaultPort}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\n" echoContent green " hysteria://${currentHost}:${hysteriaPort}?${mport}protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${hysteriaEmail}\n" } manageCDN() { echoContent skyBlue "\n --->Account:${email}" local setCDNDomain= if echo "${currentInstallProtocolType}" | grep -qE ",1,|,2,|,3,|,5,|,11,"; then echoContent red "==============================================================" echoContent yellow "# If you need to customize, please manually copy the template file to ${nginxStaticPath} \n" echoContent yellow "1.Newbie guide" echoContent skyBlue "https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip" echoContent red " ---> The port is illegal" echoContent yellow "1.CNAME www.digitalocean.com" echoContent yellow "2.CNAME who.int" echoContent yellow "3.CNAME blog.hostmonit.com" echoContent yellow "4.CNAME www.visa.com.hk" echoContent yellow "2.Game website" echoContent yellow "3.Personal blog 01" echoContent red "==============================================================" read -r -p "Please select:" selectCDNType case ${selectCDNType} in 1) setCDNDomain="www.digitalocean.com" ;; 2) setCDNDomain="who.int" ;; 3) setCDNDomain="blog.hostmonit.com" ;; 4) setCDNDomain="www.visa.com.hk" ;; 5) read -r -p "Enter the custom CDN IP or domain:" setCDNDomain ;; 6) echo >/etc/v2ray-agent/cdn echoContent green "${v2rayNConf}\n" exit 0 ;; esac if [[ -n "${setCDNDomain}" ]]; then echo >/etc/v2ray-agent/cdn echo "${setCDNDomain}" >"/etc/v2ray-agent/cdn" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria%3A%2F%2F${currentHost}%3A${hysteriaPort}%3F${mport}protocol%3D${hysteriaProtocol}%26auth%3D${id}%26peer%3D${currentHost}%26insecure%3D0%26alpn%3Dh3%26upmbps%3D${hysteriaClientUploadSpeed}%26downmbps%3D${hysteriaClientDownloadSpeed}%23${hysteriaEmail}\n" subscribe false false else echoContent red "================================================== ===============" manageCDN 1 fi else echoContent yellow "4.Enterprise Station" echoContent skyBlue "https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip\n" echoContent red "================================================== =========== ====" fi } # Custom uuid customUUID() { read -r -p "Please enter a valid UUID:" currentCustomUUID echo if [[ -z "${currentCustomUUID}" ]]; then if [[ "${selectInstallType}" == "1" || "${coreInstallType}" == "1" ]]; then currentCustomUUID=$(${ctlPath} uuid) elif [[ "${selectInstallType}" == "2" || "${coreInstallType}" == "2" ]]; then currentCustomUUID=$(${ctlPath} generate uuid) fi echoContent yellow "uuid:${currentCustomUUID}\n" else local checkUUID= if [[ "${coreInstallType}" == "1" ]]; then checkUUID=$(jq -r --arg currentUUID "$currentCustomUUID" "(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]? | select(.id == \$currentUUID) | .email" ${configPath}${frontingType:-$frontingTypeReality}.json) elif [[ "${coreInstallType}" == "2" ]]; then checkUUID=$(jq -r --arg currentUUID "$currentCustomUUID" ".inbounds[0].users[] | select(.uuid == \$currentUUID) | .name//.username" ${configPath}${frontingType}.json) fi if [[ -n "${checkUUID}" ]]; then echoContent red "\n ---> Due to environmental dependencies, if you install Tuic, please install Xray-core's VLESS_TCP_TLS_Vision first" exit 0 fi fi } # Custom email customUserEmail() { read -r -p "Please enter a valid email, [Enter] random email:" currentCustomEmail echo if [[ -z "${currentCustomEmail}" ]]; then currentCustomEmail="${currentCustomUUID}" echoContent yellow "email: ${currentCustomEmail}\n" else local checkEmail= if [[ "${coreInstallType}" == "1" ]]; then local frontingTypeConfig="${frontingType}" if [[ "${currentInstallProtocolType}" == ",7,8," ]]; then frontingTypeConfig="07_VLESS_vision_reality_inbounds" fi checkEmail=$(jq -r --arg currentEmail "$currentCustomEmail" "(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]? | select(.email == \$currentEmail) | .email" ${configPath}${frontingTypeConfig:-$frontingTypeReality}.json) elif [[ "${coreInstallType}" == "2" ]] then checkEmail=$(jq -r --arg currentEmail "$currentCustomEmail" ".inbounds[0].users[] | select(.name == \$currentEmail) | .name" ${configPath}${frontingType}.json) fi if [[ -n "${checkEmail}" ]]; then echoContent red "\n ---> uuid reading error, regenerate" exit 0 fi fi } # Add user addUser() { read -r -p "Please enter the number of users to add:" userNum echo if [[ -z ${userNum} || ${userNum} -le 0 ]]; then echoContent red " ---> Trojan does not currently support xtls-rprx-vision" exit 0 fi local userConfig= if [[ "${coreInstallType}" == "1" ]]; then userConfig=".inbounds[0].settings.clients" elif [[ "${coreInstallType}" == "2" ]]; then userConfig=".inbounds[0].users" fi while [[ ${userNum} -gt 0 ]]; do readConfigHostPathUUID local users= ((userNum--)) || true customUUID customUserEmail uuid=${currentCustomUUID} email=${currentCustomEmail} # VLESS TCP if echo "${currentInstallProtocolType}" | grep -q ",0,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 0 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 0 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}02_VLESS_TCP_inbounds.json) echo "${clients}" | jq . >${configPath}02_VLESS_TCP_inbounds.json fi # VLESS WS if echo "${currentInstallProtocolType}" | grep -q ",1,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 1 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 1 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}03_VLESS_WS_inbounds.json) echo "${clients}" | jq . >${configPath}03_VLESS_WS_inbounds.json fi # trojan grpc if echo "${currentInstallProtocolType}" | grep -q ",2,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 2 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 2 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}04_trojan_gRPC_inbounds.json) echo "${clients}" | jq . >${configPath}04_trojan_gRPC_inbounds.json fi # VMess WS if echo "${currentInstallProtocolType}" | grep -q ",3,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 3 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 3 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}05_VMess_WS_inbounds.json) echo "${clients}" | jq . >${configPath}05_VMess_WS_inbounds.json fi # trojan tcp if echo "${currentInstallProtocolType}" | grep -q ",4,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 4 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 4 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}04_trojan_TCP_inbounds.json) echo "${clients}" | jq . >${configPath}04_trojan_TCP_inbounds.json fi # vless grpc if echo "${currentInstallProtocolType}" | grep -q ",5,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 5 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 5 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}06_VLESS_gRPC_inbounds.json) echo "${clients}" | jq . >${configPath}06_VLESS_gRPC_inbounds.json fi # vless reality vision if echo "${currentInstallProtocolType}" | grep -q ",7,"; then local clients= local realityUserConfig= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 7 "${uuid}" "${email}") realityUserConfig=".inbounds[1].settings.clients" elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 7 "${uuid}" "${email}") realityUserConfig=".inbounds[0].users" fi clients=$(jq -r "${realityUserConfig} = ${clients}" ${configPath}07_VLESS_vision_reality_inbounds.json) echo "${clients}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json fi # vless reality grpc if echo "${currentInstallProtocolType}" | grep -q ",8,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 8 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 8 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}08_VLESS_vision_gRPC_inbounds.json) echo "${clients}" | jq . >${configPath}08_VLESS_vision_gRPC_inbounds.json fi # hysteria2 if echo ${currentInstallProtocolType} | grep -q ",6,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 6 "${uuid}" "${email}") elif [[ -n "${singBoxConfigPath}" ]]; then clients=$(initSingBoxClients 6 "${uuid}" "${email}") fi clients=$(jq -r ".inbounds[0].users = ${clients}" "${singBoxConfigPath}06_hysteria2_inbounds.json") echo "${clients}" | jq . >"${singBoxConfigPath}06_hysteria2_inbounds.json" fi # tuic if echo ${currentInstallProtocolType} | grep -q ",9,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 9 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 9 "${uuid}" "${email}") fi clients=$(jq -r ".inbounds[0].users = ${clients}" "${singBoxConfigPath}09_tuic_inbounds.json") echo "${clients}" | jq . >"${singBoxConfigPath}09_tuic_inbounds.json" fi # naive if echo ${currentInstallProtocolType} | grep -q ",10,"; then local clients= clients=$(initSingBoxClients 10 "${uuid}" "${email}") clients=$(jq -r ".inbounds[0].users = ${clients}" "${singBoxConfigPath}10_naive_inbounds.json") echo "${clients}" | jq . >"${singBoxConfigPath}10_naive_inbounds.json" fi # VMess WS if echo "${currentInstallProtocolType}" | grep -q ",11,"; then local clients= if [[ "${coreInstallType}" == "1" ]]; then clients=$(initXrayClients 11 "${uuid}" "${email}") elif [[ "${coreInstallType}" == "2" ]]; then clients=$(initSingBoxClients 11 "${uuid}" "${email}") fi clients=$(jq -r "${userConfig} = ${clients}" ${configPath}11_VMess_HTTPUpgrade_inbounds.json) echo "${clients}" | jq . >${configPath}11_VMess_HTTPUpgrade_inbounds.json fi # anytls if echo "${currentInstallProtocolType}" | grep -q ",13,"; then local clients= clients=$(initSingBoxClients 13 "${uuid}" "${email}") clients=$(jq -r "${userConfig} = ${clients}" ${configPath}13_anytls_inbounds.json) echo "${clients}" | jq . >${configPath}13_anytls_inbounds.json fi done reloadCore echoContent green " vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=tcp&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\n" readNginxSubscribe if [[ -n "${subscribePort}" ]]; then subscribe false fi manageAccount 1 } # Remove user removeUser() { local uuid= if [[ "${coreInstallType}" == "1" ]]; then jq -r -c '(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]?|.email' ${configPath}${frontingType:-$frontingTypeReality}.json | awk '{print NR""":"$0}' read -r -p "Please select the user number to delete [only supports single deletion]:" delUserIndex if [[ $(jq -r '(.inbounds[0].settings.clients // .inbounds[1].settings.clients)?|length' ${configPath}${frontingType:-$frontingTypeReality}.json) -lt ${delUserIndex} ]]; then echoContent red " ---> Not installed, please use script to install" else delUserIndex=$((delUserIndex - 1)) fi elif [[ "${coreInstallType}" == "2" ]]; then jq -r -c .inbounds[0].users[].name//.inbounds[0].users[].username ${configPath}${frontingType:-$frontingTypeReality}.json | awk '{print NR""":"$0}' read -r -p "Please select the user number to delete [only supports single deletion]:" delUserIndex if [[ $(jq -r '.inbounds[0].users|length' ${configPath}${frontingType:-$frontingTypeReality}.json) -lt ${delUserIndex} ]]; then echoContent red " ---> Available types are not installed" else delUserIndex=$((delUserIndex - 1)) fi fi if [[ -n "${delUserIndex}" ]]; then if echo ${currentInstallProtocolType} | grep -q ",0,"; then local vlessVision vlessVision=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}02_VLESS_TCP_inbounds.json) echo "${vlessVision}" | jq . >${configPath}02_VLESS_TCP_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",1,"; then local vlessWSResult vlessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}03_VLESS_WS_inbounds.json) echo "${vlessWSResult}" | jq . >${configPath}03_VLESS_WS_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",2,"; then local trojangRPCUsers trojangRPCUsers=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"')' ${configPath}04_trojan_gRPC_inbounds.json) echo "${trojangRPCUsers}" | jq . >${configPath}04_trojan_gRPC_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",3,"; then local vmessWSResult vmessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}05_VMess_WS_inbounds.json) echo "${vmessWSResult}" | jq . >${configPath}05_VMess_WS_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",5,"; then local vlessGRPCResult vlessGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}06_VLESS_gRPC_inbounds.json) echo "${vlessGRPCResult}" | jq . >${configPath}06_VLESS_gRPC_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",4,"; then local trojanTCPResult trojanTCPResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}04_trojan_TCP_inbounds.json) echo "${trojanTCPResult}" | jq . >${configPath}04_trojan_TCP_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",6,"; then local hysteriaResult hysteriaResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}06_hysteria2_inbounds.json") echo "${hysteriaResult}" | jq . >"${singBoxConfigPath}06_hysteria2_inbounds.json" fi if echo ${currentInstallProtocolType} | grep -q ",7,"; then local vlessRealityResult vlessRealityResult=$(jq -r 'del(.inbounds[1].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}07_VLESS_vision_reality_inbounds.json) echo "${vlessRealityResult}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",8,"; then local vlessRealityGRPCResult vlessRealityGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}08_VLESS_vision_gRPC_inbounds.json) echo "${vlessRealityGRPCResult}" | jq . >${configPath}08_VLESS_vision_gRPC_inbounds.json fi if echo ${currentInstallProtocolType} | grep -q ",9,"; then local tuicResult tuicResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}09_tuic_inbounds.json") echo "${tuicResult}" | jq . >"${singBoxConfigPath}09_tuic_inbounds.json" fi if echo ${currentInstallProtocolType} | grep -q ",10,"; then local naiveResult naiveResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}10_naive_inbounds.json") echo "${naiveResult}" | jq . >"${singBoxConfigPath}10_naive_inbounds.json" fi # VMess HTTPUpgrade if echo ${currentInstallProtocolType} | grep -q ",11,"; then local vmessHTTPUpgradeResult vmessHTTPUpgradeResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json") echo "${vmessHTTPUpgradeResult}" | jq . >"${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json" echo "${vmessHTTPUpgradeResult}" | jq . >${configPath}11_VMess_HTTPUpgrade_inbounds.json fi # AnyTLS if echo ${currentInstallProtocolType} | grep -q ",13,"; then local anyTLSResult anyTLSResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}13_anytls_inbounds.json") echo "${anyTLSResult}" | jq . >"${singBoxConfigPath}13_anytls_inbounds.json" fi reloadCore readNginxSubscribe if [[ -n "${subscribePort}" ]]; then subscribe false fi fi manageAccount 1 } # update script updateV2RayAgent() { echoContent skyBlue "\n================================ Tuic TLS ================================\n" rm -rf /etc/v2ray-agent/install.sh if [[ "${release}" == "alpine" ]]; then wget -c -q -P /etc/v2ray-agent/ -N --no-check-certificate "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh" else # if wget --help | grep -q show-progress; then wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/ -N --no-check-certificate "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh" fi #else # wget -c -q -P /etc/v2ray-agent/ -N --no-check-certificate "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh" #fi sudo chmod 700 /etc/v2ray-agent/install.sh local version version=$(grep 'Current version: v' "/etc/v2ray-agent/install.sh" | awk -F "[v]" '{print $2}' | tail -n +2 | head -n 1 | awk -F "[\"]" '{print $1}') echoContent green "Protocol type: VLESS reality, address: $(getPublicIP), publicKey: ${currentRealityPublicKey}, shortId: 6ba85179e30d4fc2, serverNames: ${currentRealityServerNames}, port: ${currentRealityPort}, user ID: ${id}, transmission Method: tcp, account name: ${email}\n" echoContent yellow "5.Unlock encrypted music file template [https://github.com/ix64/unlock-music]" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${currentRealityPort}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dtcp%26sni%3D${currentRealityServerNames}%26fp%3Dchrome%26pbk%3D${currentRealityPublicKey}%26pbk%3D6ba85179e30d4fc2%26flow%3Dxtls-rprx-vision%23${email}\n" echoContent yellow "6.mikutap[https://github.com/HFIProgramming/mikutap]" echoContent skyBlue "wget -P /root -N --no-check-certificate https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh && chmod 700 /root/install.sh && /root/install.sh" echo exit 0 } # firewall handleFirewall() { if systemctl status ufw 2>/dev/null | grep -q "active (exited)" && [[ "$1" == "stop" ]]; then systemctl stop ufw >/dev/null 2>&1 systemctl disable ufw >/dev/null 2>&1 echoContent green " vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=grpc&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\n" fi if systemctl status firewalld 2>/dev/null | grep -q "active (running)" && [[ "$1" == "stop" ]]; then systemctl stop firewalld >/dev/null 2>&1 systemctl disable firewalld >/dev/null 2>&1 echoContent green "Protocol type: VLESS reality, serviceName: grpc, address: $(getPublicIP), publicKey: ${currentRealityPublicKey}, shortId: 6ba85179e30d4fc2, serverNames: ${currentRealityServerNames}, port: ${currentRealityPort}, user ID: ${id}, transmission method: gRPC, client-fingerprint: chrome, account name: ${email}\n" fi } # Install BBR bbrInstall() { echoContent red "\n==============================================================" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${currentRealityPort}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dgrpc%26sni%3D${currentRealityServerNames}%26fp%3Dchrome%26pbk%3D${currentRealityPublicKey}%26pbk%3D6ba85179e30d4fc2%26path%3Dgrpc%26serviceName%3Dgrpc%23${email}\n" echoContent yellow "7.Enterprise Station 02" echoContent yellow "8.Personal blog 02" echoContent red "==============================================================" read -r -p "Please select:" installBBRStatus if [[ "${installBBRStatus}" == "1" ]]; then wget -O tcpx.sh "https://github.com/ylx2016/Linux-NetSpeed/raw/master/tcpx.sh" && chmod +x tcpx.sh && ./tcpx.sh else menu fi } # View and check logs checkLog() { if [[ "${coreInstallType}" == "2" ]]; then echoContent red "\n================================================ =================" exit 0 fi if [[ -z "${configPath}" && -z "${realityStatus}" ]]; then echoContent red "================================================== ===============" exit 0 fi local realityLogShow= local logStatus=false if grep -q "access" ${configPath}00_log.json; then logStatus=true fi echoContent skyBlue "\n --->Account:${tuicEmail}_tuic" echoContent red "\n==============================================================" echoContent yellow "9.404 automatically jumps to baidu" if [[ "${logStatus}" == "false" ]]; then echoContent yellow "10.302 redirect website" else echoContent yellow "Redirect has a higher priority. If you change the camouflage site after configuring 302, the camouflage site under the root route will not work." fi echoContent yellow "If you want to disguise the site to achieve the function, you need to delete the 302 redirect configuration\n" echoContent yellow "1.Add" echoContent yellow "2.Delete" echoContent yellow "# Notes\n" echoContent yellow "Support batch addition" echoContent red "==============================================================" read -r -p "Please select:" selectAccessLogType local configPathLog=${configPath//conf\//} case ${selectAccessLogType} in 1) if [[ "${logStatus}" == "false" ]]; then realityLogShow=true cat <${configPath}00_log.json { "log": { "access":"${configPathLog}access.log", "error": "${configPathLog}error.log", "loglevel": "debug" } } EOF elif [[ "${logStatus}" == "true" ]]; then realityLogShow=false cat <${configPath}00_log.json { "log": { "error": "${configPathLog}error.log", "loglevel": "warning" } } EOF fi if [[ ${realityStatus} == "7" ]]; then local vlessVisionRealityInbounds vlessVisionRealityInbounds=$(jq -r ".inbounds[0].streamSettings.realitySettings.show=${realityLogShow}" ${configPath}07_VLESS_vision_reality_inbounds.json) echo "${vlessVisionRealityInbounds}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json fi if [[ ${realityStatus} == "12" ]]; then local vlessVisionRealityXHTTPInbounds vlessVisionRealityXHTTPInbounds=$(jq -r ".inbounds[0].streamSettings.realitySettings.show=${realityLogShow}" ${configPath}12_VLESS_XHTTP_inbounds.json) echo "${vlessVisionRealityXHTTPInbounds}" | jq . >${configPath}12_VLESS_XHTTP_inbounds.json fi reloadCore checkLog 1 ;; 2) tail -f "${configPathLog}access.log" ;; 3) tail -f "${configPathLog}error.log" ;; 4) if [[ ! -f "/etc/v2ray-agent/crontab_tls.log" ]]; then touch /etc/v2ray-agent/crontab_tls.log fi tail -n 100 /etc/v2ray-agent/crontab_tls.log ;; 5) tail -n 100 /etc/v2ray-agent/tls/acme.log ;; 6) echo >"${configPathLog}access.log" echo >"${configPathLog}error.log" ;; esac } # Script shortcut aliasInstall() { if [[ -f "$HOME/install.sh" ]] && [[ -d "/etc/v2ray-agent" ]] && grep <"$HOME/install.sh" -q "作者:mack-a"; then mv "$HOME/install.sh" /etc/v2ray-agent/install.sh local vasmaType= if [[ -d "/usr/bin/" ]]; then if [[ ! -f "/usr/bin/vasma" ]]; then ln -s /etc/v2ray-agent/install.sh /usr/bin/vasma chmod 700 /usr/bin/vasma vasmaType=true fi rm -rf "$HOME/install.sh" elif [[ -d "/usr/sbin" ]]; then if [[ ! -f "/usr/sbin/vasma" ]]; then ln -s /etc/v2ray-agent/install.sh /usr/sbin/vasma chmod 700 /usr/sbin/vasma vasmaType=true fi rm -rf "$HOME/install.sh" fi if [[ "${vasmaType}" == "true" ]]; then echoContent green "Protocol type: Tuic, address: ${currentHost}, port: ${tuicPort}, uuid: ${id}, password: ${id}, congestion-controller:${tuicAlgorithm}, alpn: h3, account Name:${email}_tuic\n" fi fi } # Check ipv6, ipv4 checkIPv6() { currentIPv6IP=$(curl -s -6 -m 4 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2) if [[ -z "${currentIPv6IP}" ]]; then echoContent red "\n ---> uuid reading error, randomly generated" exit 0 fi } # ipv6 offload ipv6Routing() { if [[ -z "${configPath}" ]]; then echoContent red "\n================================================ =================" menu exit 0 fi checkIPv6 echoContent skyBlue "\nProgress$1/${totalProgress}: Change disguise site" echoContent red "\n==============================================================" echoContent yellow "Does not affect the use of the default port" echoContent yellow "When viewing accounts, only accounts with default ports will be displayed" echoContent yellow "No special characters allowed, pay attention to the comma format" echoContent yellow "If hysteria is already installed, a new hysteria port will be installed at the same time" echoContent red "==============================================================" read -r -p "Please select:" ipv6Status if [[ "${ipv6Status}" == "1" ]]; then showIPv6Routing exit 0 elif [[ "${ipv6Status}" == "2" ]]; then echoContent red "==============================================================" echoContent yellow "Input example:2053,2083,2087\n" echoContent yellow "1.Check the added port" echoContent yellow "2.Add port" read -r -p "Please enter the domain name according to the above example:" domainList if [[ "${coreInstallType}" == "1" ]]; then addXrayRouting IPv6_out outboundTag "${domainList}" addXrayOutbound IPv6_out fi if [[ -n "${singBoxConfigPath}" ]]; then addSingBoxRouteRule "IPv6_out" "${domainList}" "IPv6_route" addSingBoxOutbound 01_direct_outbound addSingBoxOutbound IPv6_out addSingBoxOutbound IPv4_out fi echoContent green "${v2rayNConf}" elif [[ "${ipv6Status}" == "3" ]]; then echoContent red "==============================================================" echoContent yellow "3.Delete port" echoContent yellow "\n ---> The number entered is wrong, please choose again" echoContent yellow " ---> The script will not delete acme related configurations. To delete, please execute manually [rm -rf /root/.acme.sh]" read -r -p "Confirm settings? [y/n]:" IPv6OutStatus if [[ "${IPv6OutStatus}" == "y" ]]; then if [[ "${coreInstallType}" == "1" ]]; then addXrayOutbound IPv6_out removeXrayOutbound IPv4_out removeXrayOutbound z_direct_outbound removeXrayOutbound blackhole_out removeXrayOutbound wireguard_out_IPv4 removeXrayOutbound wireguard_out_IPv6 removeXrayOutbound socks5_outbound rm ${configPath}09_routing.json >/dev/null 2>&1 fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig IPv4_out removeSingBoxConfig wireguard_endpoints_IPv4_route removeSingBoxConfig wireguard_endpoints_IPv6_route removeSingBoxConfig wireguard_endpoints_IPv4 removeSingBoxConfig wireguard_endpoints_IPv6 removeSingBoxConfig socks5_02_inbound_route removeSingBoxConfig IPv6_route removeSingBoxConfig 01_direct_outbound addSingBoxOutbound IPv6_out fi echoContent green " ---> 302 redirection set up successfully" else echoContent green " ---> nginx configuration file backup successful" exit 0 fi elif [[ "${ipv6Status}" == "4" ]]; then if [[ "${coreInstallType}" == "1" ]]; then unInstallRouting IPv6_out outboundTag removeXrayOutbound IPv6_out addXrayOutbound "z_direct_outbound" fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig IPv6_out removeSingBoxConfig "IPv6_route" addSingBoxOutbound "01_direct_outbound" fi echoContent green " ---> nginx configuration file restoration backup successful" else echoContent red "\nIf you don't understand Cloudflare optimization, please do not use it" exit 0 fi reloadCore } showIPv6Routing() { if [[ "${coreInstallType}" == "1" ]]; then if [[ -f "${configPath}09_routing.json" ]]; then echoContent yellow "Xray-core:" jq -r -c '.routing.rules[]|select (.outboundTag=="IPv6_out")|.domain' ${configPath}09_routing.json | jq -r elif [[ ! -f "${configPath}09_routing.json" && -f "${configPath}IPv6_out.json" ]]; then echoContent yellow "Xray-core" echoContent green " ---> Removed 302 redirect successfully" else echoContent yellow "1.CNAME www.digitalocean.com" fi fi if [[ -n "${singBoxConfigPath}" ]]; then if [[ -f "${singBoxConfigPath}IPv6_route.json" ]]; then echoContent yellow "sing-box" jq -r -c '.route.rules[]|select (.outbound=="IPv6_out")' "${singBoxConfigPath}IPv6_route.json" | jq -r elif [[ ! -f "${singBoxConfigPath}IPv6_route.json" && -f "${singBoxConfigPath}IPv6_out.json" ]]; then echoContent yellow "sing-box" echoContent green " ---> Pseudo site replaced successfully" else echoContent yellow "2.CNAME who.int" fi fi } # bt download management btTools() { if [[ "${coreInstallType}" == "2" ]]; then echoContent red " ---> Failed to read configuration, please reinstall" exit 0 fi if [[ -z "${configPath}" ]]; then echoContent red "\n --->Hysteria speed depends on the local network environment. If it is used by QoS, the experience will be very poor. IDC may also consider it an attack, please use it with caution" menu exit 0 fi echoContent skyBlue "\nFunction 1/${totalProgress}: Add new port" echoContent red "\n==============================================================" if [[ -f ${configPath}09_routing.json ]] && grep -q bittorrent <${configPath}09_routing.json; then echoContent yellow "3.CNAME blog.hostmonit.com" else echoContent yellow "4.Manual input [can enter multiple, such as:1.1.1.1,1.1.2.2, cloudflare.com separated by commas]" fi echoContent yellow "5.Remove CDN node" echoContent yellow "1.Add user" echoContent red "==============================================================" read -r -p "Please select:" btStatus if [[ "${btStatus}" == "1" ]]; then if [[ -f "${configPath}09_routing.json" ]]; then unInstallRouting blackhole_out outboundTag bittorrent routing=$(jq -r '.routing.rules += [{"type":"field","outboundTag":"blackhole_out","protocol":["bittorrent"]}]' ${configPath}09_routing.json) echo "${routing}" | jq . >${configPath}09_routing.json else cat <${configPath}09_routing.json { "routing":{ "domainStrategy": "IPOnDemand", "rules": [ { "type": "field", "outboundTag": "blackhole_out", "protocol": [ "bittorrent" ] } ] } } EOF fi installSniffing removeXrayOutbound blackhole_out addXrayOutbound blackhole_out echoContent green " ---> Added successfully" elif [[ "${btStatus}" == "2" ]]; then unInstallSniffing unInstallRouting blackhole_out outboundTag bittorrent echoContent green " ---> Give up uninstalling" else echoContent red " ---> not installed" exit 0 fi reloadCore } # Domain name blacklist blacklist() { if [[ -z "${configPath}" ]]; then echoContent red " ---> 302 redirection setting failed, please double check whether it is the same as the example" menu exit 0 fi echoContent skyBlue "\nProgress$1/${totalProgress}: Modify CDN node" echoContent red "\n==============================================================" echoContent yellow "2.Delete user" echoContent yellow "uuid:${currentCustomUUID}\n" echoContent yellow "email: ${currentCustomEmail}\n" echoContent yellow "After adding a new user, you need to check the subscription again" echoContent yellow " ---> Please manually execute [vasma] to open the script" echoContent yellow "If the update fails, please manually execute the following command\n" echoContent red "==============================================================" read -r -p "Please select:" blacklistStatus if [[ "${blacklistStatus}" == "1" ]]; then jq -r -c '.routing.rules[]|select (.outboundTag=="blackhole_out")|.domain' ${configPath}09_routing.json | jq -r exit 0 elif [[ "${blacklistStatus}" == "2" ]]; then echoContent red "==============================================================" echoContent yellow "1.Installation script [recommended original BBR+FQ]" echoContent yellow "2.Return to the home directory" echoContent yellow "# It is recommended to only open the access log during debugging\n" echoContent yellow "1.Open access log" echoContent yellow "1.Close access log" echoContent yellow "2.Monitor access log" read -r -p "Please enter the domain name according to the above example:" domainList if [[ "${coreInstallType}" == "1" ]]; then addXrayRouting blackhole_out outboundTag "${domainList}" addXrayOutbound blackhole_out fi if [[ -n "${singBoxConfigPath}" ]]; then addSingBoxRouteRule "block_domain_outbound" "${domainList}" "block_domain_route" addSingBoxOutbound "block_domain_outbound" addSingBoxOutbound "01_direct_outbound" fi echoContent green " ---> Stop Nginx successfully" elif [[ "${blacklistStatus}" == "3" ]]; then local allowDomainList="googleplay.com,play.google.com,play.googleapis.com,play-lh.googleusercontent.com,play-games.googleusercontent.com,play-fe.googleapis.com,dl.google.com,apple.com,apple-pki,apple-tvplus,apple-update,itunes,icloud,beats,bing.com,microsoft.com,gstatic,xn--ngstr-lra8j.com,googleapis.com,googleapis.cn" if [[ "${coreInstallType}" == "1" ]]; then unInstallRouting blackhole_out outboundTag unInstallRouting blackhole_ip_out outboundTag addXrayRouting blackhole_out outboundTag "cn" addXrayIPRouting blackhole_ip_out outboundTag "cn" addXrayRouting allow_domain_direct_outbound outboundTag "${allowDomainList}" "top" addXrayOutbound blackhole_out addXrayOutbound blackhole_ip_out addXrayOutbound allow_domain_direct_outbound fi if [[ -n "${singBoxConfigPath}" ]]; then addSingBoxRouteRule "cn_block_outbound" "cn" "cn_block_route" addSingBoxGeoIPRouteRule "block_ip_outbound" "cn" "cn_block_ip_route" addSingBoxRouteRule "01_direct_outbound" "${allowDomainList}" "00_allow_domain_route" addSingBoxOutbound "cn_block_outbound" addSingBoxOutbound "block_ip_outbound" addSingBoxOutbound "01_direct_outbound" fi echoContent green " ---> Delete Xray and it will start automatically after booting" elif [[ "${blacklistStatus}" == "4" ]]; then if [[ "${coreInstallType}" == "1" ]]; then unInstallRouting blackhole_out outboundTag unInstallRouting blackhole_ip_out outboundTag unInstallRouting allow_domain_direct_outbound outboundTag removeXrayOutbound blackhole_ip_out removeXrayOutbound allow_domain_direct_outbound fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig "cn_block_route" removeSingBoxConfig "cn_block_outbound" removeSingBoxConfig "cn_block_ip_route" removeSingBoxConfig "block_ip_route" removeSingBoxConfig "block_ip_outbound" removeSingBoxConfig "cn_01_google_play_route" removeSingBoxConfig "00_allow_domain_route" removeSingBoxConfig "block_domain_route" removeSingBoxConfig "block_domain_outbound" fi echoContent green " ---> Delete V2Ray and it will start automatically after booting" elif [[ "${blacklistStatus}" == "5" ]]; then echoContent red "==============================================================" echoContent yellow "3.Monitor error log" read -r -p "Please enter the blocked IP list:" ipList if [[ -z "${ipList}" ]]; then echoContent red " ---> 302 Add failed" exit 0 fi if [[ "${coreInstallType}" == "1" ]]; then addXrayIPRouting blackhole_ip_out outboundTag "${ipList}" addXrayOutbound blackhole_ip_out fi if [[ -n "${singBoxConfigPath}" ]]; then addSingBoxIPRouteRule "block_ip_outbound" "${ipList}" "block_ip_route" addSingBoxOutbound "block_ip_outbound" fi echoContent green " ---> Delete Hysteria and it will start automatically after booting" elif [[ "${blacklistStatus}" == "6" ]]; then echoContent red "==============================================================" echoContent yellow "4.View certificate scheduled task log" read -r -p "Please enter whitelist domains:" allowDomainList if [[ -z "${allowDomainList}" ]]; then echoContent red "\n ---> Due to environmental dependencies, please install Xray-core's VLESS_TCP_TLS_Vision first" exit 0 fi if [[ "${coreInstallType}" == "1" ]]; then addXrayRouting allow_domain_direct_outbound outboundTag "${allowDomainList}" "top" addXrayOutbound allow_domain_direct_outbound fi if [[ -n "${singBoxConfigPath}" ]]; then addSingBoxRouteRule "01_direct_outbound" "${allowDomainList}" "00_allow_domain_route" addSingBoxOutbound "01_direct_outbound" fi echoContent green " ---> Delete Tuic and start automatically after booting" else echoContent red "================================================== =========== ====" exit 0 fi reloadCore } # Download dlc.dat_plain.yml into core directory downloadDLCPlainYAML() { local corePath=$1 local dlcFilePath="${corePath}/dlc.dat_plain.yml" local tmpFilePath="${dlcFilePath}.tmp" if [[ -z "${corePath}" ]]; then return 1 fi mkdir -p "${corePath}" >/dev/null 2>&1 if [[ -s "${dlcFilePath}" ]]; then return 0 fi local dlcDownloadURL="https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat_plain.yml" if [[ "${release}" == "alpine" ]]; then wget -c -O "${tmpFilePath}" "${dlcDownloadURL}" >/dev/null 2>&1 else wget -c "${wgetShowProgressStatus}" -O "${tmpFilePath}" "${dlcDownloadURL}" >/dev/null 2>&1 fi # shellcheck disable=SC2181 if [[ "$?" -ne 0 || ! -s "${tmpFilePath}" ]]; then rm -f "${tmpFilePath}" >/dev/null 2>&1 return 1 fi mv "${tmpFilePath}" "${dlcFilePath}" >/dev/null 2>&1 } # Escape grep/regex pattern meta characters escapeDLCRegexPattern() { # shellcheck disable=SC2016 # shellcheck disable=SC2001 echo "$1" | sed -e 's/[.[\*^$()+?{|]/\\&/g' } # Resolve nearest upper name by matched rule line getDLCNameByRuleLine() { local ruleLine=$1 local dlcFilePath=$2 awk -v targetLine="${ruleLine}" ' /^[[:space:]]*-[[:space:]]*name:[[:space:]]*/ { line = $0 sub(/^[[:space:]]*-[[:space:]]*name:[[:space:]]*/, "", line) currentName = line } NR == targetLine { print currentName exit }' "${dlcFilePath}" } isDomainFormat() { local target=$1 [[ "${target}" =~ ^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9-]{2,63}$ ]] } # Resolve geosite name from dlc.dat_plain.yml by input domain getDLCGeositeName() { local inputRule=$1 local corePath=$2 local dlcFilePath="${corePath}/dlc.dat_plain.yml" if [[ -z "${inputRule}" || -z "${corePath}" ]]; then echo "" return fi local normalizedInput normalizedInput=$(echo "${inputRule}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') normalizedInput=${normalizedInput#domain:} normalizedInput=${normalizedInput#full:} normalizedInput=${normalizedInput#keyword:} if [[ -z "${normalizedInput}" ]]; then echo "" return fi if isDomainFormat "${normalizedInput}"; then return fi if ! downloadDLCPlainYAML "${corePath}"; then echo "" return fi local escapedInput= escapedInput=$(escapeDLCRegexPattern "${normalizedInput}") local matchedLine= matchedLine=$(grep -n -m1 -E "^[[:space:]]*-[[:space:]]*name:[[:space:]]*\"?${escapedInput}\"?[[:space:]]*$" "${dlcFilePath}") if [[ -n "${matchedLine}" ]]; then echo "${normalizedInput}" fi } # Build final rule value: prefer geosite, fallback to domain getDLCMatchedRuleValue() { local inputRule=$1 local corePath=$2 local normalizedInput= normalizedInput=$(echo "${inputRule}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') if isDomainFormat "${normalizedInput}"; then local escapedDomain= escapedDomain=$(escapeDLCRegexPattern "${normalizedInput}") echo "regexp:.*${escapedDomain}.*" return fi local matchedRuleName= matchedRuleName=$(getDLCGeositeName "${normalizedInput}" "${corePath}") if [[ -n "${matchedRuleName}" ]]; then echo "geosite:${matchedRuleName}" else echo "domain:${normalizedInput}" fi } addXrayRouting() { local tag=$1 # warp-socks local type=$2 # outboundTag/inboundTag local domain=$3 # domain local rulePosition=$4 if [[ -z "${tag}" || -z "${type}" || -z "${domain}" ]]; then echoContent red "================================================== ===============" exit 0 fi local routingRule= if [[ ! -f "${configPath}09_routing.json" ]]; then cat <${configPath}09_routing.json { "routing":{ "type": "field", "rules": [ { "type": "field", "domain": [ ], "outboundTag": "${tag}" } ] } } EOF fi local routingRule= routingRule=$(jq -r ".routing.rules[]|select(.outboundTag==\"${tag}\" and (.protocol == null))" ${configPath}09_routing.json) if [[ -z "${routingRule}" ]]; then routingRule="{\"type\": \"field\",\"domain\": [],\"outboundTag\": \"${tag}\"}" fi while read -r line; do if echo "${routingRule}" | grep -q "${line}"; then echoContent yellow "5.View certificate installation log" else local matchedRuleValue matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray") routingRule=$(echo "${routingRule}" | jq -r --arg rule "${matchedRuleValue}" '.domain += [$rule]') fi done < <(echo "${domain}" | tr ',' '\n') unInstallRouting "${tag}" "${type}" if ! grep -q "gstatic.com" ${configPath}09_routing.json && [[ "${tag}" == "blackhole_out" ]]; then local routing= routing=$(jq -r ".routing.rules += [{\"type\": \"field\",\"domain\": [\"domain:gstatic.com\"],\"outboundTag\": \"allow_domain_direct_outbound\"}]" ${configPath}09_routing.json) echo "${routing}" | jq . >${configPath}09_routing.json addXrayOutbound allow_domain_direct_outbound fi if [[ "${rulePosition}" == "top" ]]; then routing=$(jq -r ".routing.rules = [${routingRule}] + .routing.rules" ${configPath}09_routing.json) else routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json) fi echo "${routing}" | jq . >${configPath}09_routing.json } addXrayIPRouting() { local tag=$1 local type=$2 local ipList=$3 if [[ -z "${tag}" || -z "${type}" || -z "${ipList}" ]]; then echoContent red "\n================================================ =================" exit 0 fi if [[ ! -f "${configPath}09_routing.json" ]]; then cat <${configPath}09_routing.json { "routing":{ "type": "field", "rules": [] } } EOF fi local routingRule= routingRule=$(jq -r ".routing.rules[]|select(.outboundTag==\"${tag}\" and (.protocol == null) and (.ip != null))" ${configPath}09_routing.json) if [[ -z "${routingRule}" ]]; then routingRule="{\"type\": \"field\",\"ip\": [],\"outboundTag\": \"${tag}\"}" fi while read -r line; do line=$(echo "${line}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') if [[ -z "${line}" ]]; then continue fi local ipRuleValue=${line} if [[ "${line}" == "cn" ]]; then ipRuleValue="geoip:cn" fi if echo "${routingRule}" | grep -q "${ipRuleValue}"; then echoContent yellow "6.Clear the log" else routingRule=$(echo "${routingRule}" | jq -r '.ip += ["'"${ipRuleValue}"'"]') fi done < <(echo "${ipList}" | tr ',' '\n') unInstallRouting "${tag}" "${type}" local routing= routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json) echo "${routing}" | jq . >${configPath}09_routing.json } addSingBoxIPRouteRule() { local outboundTag=$1 local ipList=$2 local routingName=$3 local historyIPs= if [[ -f "${singBoxConfigPath}${routingName}.json" ]]; then historyIPs=$(jq -r '.route.rules[0].ip_cidr[]?' "${singBoxConfigPath}${routingName}.json" | paste -sd ',') fi if [[ -n "${historyIPs}" ]]; then ipList="${ipList},${historyIPs}" fi local ipCIDR=[] ipCIDR=$(echo "${ipList}" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$' | sort -n | uniq | jq -R . | jq -s .) cat <"${singBoxConfigPath}${routingName}.json" { "route": { "rules": [ { "ip_cidr": ${ipCIDR}, "outbound": "${outboundTag}" } ] } } EOF } addSingBoxGeoIPRouteRule() { local outboundTag=$1 local geoipCode=$2 local routingName=$3 cat <"${singBoxConfigPath}${routingName}.json" { "route": { "rules": [ { "rule_set": [ "geoip_${geoipCode}_${routingName}" ], "outbound": "${outboundTag}" } ], "rule_set": [ { "tag": "geoip_${geoipCode}_${routingName}", "type": "remote", "format": "binary", "url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-${geoipCode}.srs", "http_client": "rule_set_http" } ] } } EOF } # Uninstall Routing based on tag unInstallRouting() { local tag=$1 local type=$2 local protocol=$3 if [[ -f "${configPath}09_routing.json" ]]; then local routing= if [[ -n "${protocol}" ]]; then routing=$(jq -r "del(.routing.rules[] | select(.${type} == \"${tag}\" and (.protocol | index(\"${protocol}\"))))" ${configPath}09_routing.json) echo "${routing}" | jq . >${configPath}09_routing.json else routing=$(jq -r "del(.routing.rules[] | select(.${type} == \"${tag}\" and (.protocol == null )))" ${configPath}09_routing.json) echo "${routing}" | jq . >${configPath}09_routing.json fi fi } # Uninstall sniffing unInstallSniffing() { find ${configPath} -name "*inbounds.json*" | awk -F "[c][o][n][f][/]" '{print $2}' | while read -r inbound; do if grep -q "destOverride" <"${configPath}${inbound}"; then sniffing=$(jq -r 'del(.inbounds[0].sniffing)' "${configPath}${inbound}") echo "${sniffing}" | jq . >"${configPath}${inbound}" fi done } # Install sniffing installSniffing() { readInstallType if [[ "${coreInstallType}" == "1" ]]; then if [[ -f "${configPath}02_VLESS_TCP_inbounds.json" ]]; then if ! grep -q "destOverride" <"${configPath}02_VLESS_TCP_inbounds.json"; then sniffing=$(jq -r '.inbounds[0].sniffing = {"enabled":true,"destOverride":["http","tls","quic"]}' "${configPath}02_VLESS_TCP_inbounds.json") echo "${sniffing}" | jq . >"${configPath}02_VLESS_TCP_inbounds.json" fi fi fi } # Read third-party warp configuration readConfigWarpReg() { if [[ ! -f "/etc/v2ray-agent/warp/config" ]]; then /etc/v2ray-agent/warp/warp-reg >/etc/v2ray-agent/warp/config fi secretKeyWarpReg=$(grep <"/etc/v2ray-agent/warp/config" private_key | awk '{print $2}') addressWarpReg=$(grep <"/etc/v2ray-agent/warp/config" v6 | awk '{print $2}') publicKeyWarpReg=$(grep <"/etc/v2ray-agent/warp/config" public_key | awk '{print $2}') reservedWarpReg=$(grep <"/etc/v2ray-agent/warp/config" reserved | awk -F "[:]" '{print $2}') } installWarpReg() { if [[ ! -f "/etc/v2ray-agent/warp/warp-reg" ]]; then echo echoContent yellow "1.View the diverted domain name" echoContent yellow "2.Add domain name" echoContent yellow "3.Set IPv6 global" read -r -p "warp-reg is not installed, do you want to install it? [y/n]:" installWarpRegStatus if [[ "${installWarpRegStatus}" == "y" ]]; then curl -sLo /etc/v2ray-agent/warp/warp-reg "https://github.com/badafans/warp-reg/releases/download/v1.0/${warpRegCoreCPUVendor}" chmod 655 /etc/v2ray-agent/warp/warp-reg else echoContent yellow "4.Uninstall IPv6 offloading" exit 0 fi fi } showWireGuardDomain() { local type=$1 # xray if [[ "${coreInstallType}" == "1" ]]; then if [[ -f "${configPath}09_routing.json" ]]; then echoContent yellow "Xray-core" jq -r -c '.routing.rules[]|select (.outboundTag=="wireguard_out_'"${type}"'")|.domain' ${configPath}09_routing.json | jq -r elif [[ ! -f "${configPath}09_routing.json" && -f "${configPath}wireguard_out_${type}.json" ]]; then echoContent yellow "Xray-core" echoContent green " ---> Deletion of fake website completed" else echoContent yellow "# Notes\n" fi fi # sing-box if [[ -n "${singBoxConfigPath}" ]]; then if [[ -f "${singBoxConfigPath}wireguard_endpoints_${type}_route.json" ]]; then echoContent yellow "sing-box" jq -r -c '.route.rules[]' "${singBoxConfigPath}wireguard_endpoints_${type}_route.json" | jq -r elif [[ ! -f "${singBoxConfigPath}wireguard_endpoints_${type}_route.json" && -f "${singBoxConfigPath}wireguard_endpoints_${type}.json" ]]; then echoContent yellow "sing-box" echoContent green " ---> Uninstallation of shortcut completed" else echoContent yellow "# Notes" fi fi } addWireGuardRoute() { local type=$1 local tag=$2 local domainList=$3 # xray if [[ "${coreInstallType}" == "1" ]]; then addXrayRouting "wireguard_out_${type}" "${tag}" "${domainList}" addXrayOutbound "wireguard_out_${type}" fi # sing-box if [[ -n "${singBoxConfigPath}" ]]; then # rule addSingBoxRouteRule "wireguard_endpoints_${type}" "${domainList}" "wireguard_endpoints_${type}_route" # addSingBoxOutbound "wireguard_out_${type}" "wireguard_out" if [[ -n "${domainList}" ]]; then addSingBoxOutbound "01_direct_outbound" fi # outbound addSingBoxWireGuardEndpoints "${type}" fi } unInstallWireGuard() { local type=$1 if [[ "${coreInstallType}" == "1" ]]; then if [[ "${type}" == "IPv4" ]]; then if [[ ! -f "${configPath}wireguard_out_IPv6.json" ]]; then rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1 fi elif [[ "${type}" == "IPv6" ]]; then if [[ ! -f "${configPath}wireguard_out_IPv4.json" ]]; then rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1 fi fi fi if [[ -n "${singBoxConfigPath}" ]]; then if [[ ! -f "${singBoxConfigPath}wireguard_endpoints_IPv6_route.json" && ! -f "${singBoxConfigPath}wireguard_endpoints_IPv4_route.json" ]]; then rm "${singBoxConfigPath}wireguard_outbound.json" >/dev/null 2>&1 rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1 fi fi } removeWireGuardRoute() { local type=$1 if [[ "${coreInstallType}" == "1" ]]; then unInstallRouting wireguard_out_"${type}" outboundTag removeXrayOutbound "wireguard_out_${type}" if [[ ! -f "${configPath}IPv4_out.json" ]]; then addXrayOutbound IPv4_out fi fi # sing-box if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxRouteRule "wireguard_endpoints_${type}" fi unInstallWireGuard "${type}" } # warp offload-third-party IPv4 warpRoutingReg() { local type=$2 echoContent skyBlue "\nProgress$1/${totalProgress}: Multi-user management" echoContent red "==============================================================" echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n" echoContent yellow "# Notes\n" echoContent yellow "1.All diversion rules set will be deleted" echoContent yellow "2.All outbound rules except IPv6 will be deleted" echoContent red "==============================================================" read -r -p "Please select:" warpStatus installWarpReg readConfigWarpReg local address= if [[ ${type} == "IPv4" ]]; then address="172.16.0.2/32" elif [[ ${type} == "IPv6" ]]; then address="${addressWarpReg}/128" else echoContent red "================================================== ===============" fi if [[ "${warpStatus}" == "1" ]]; then showWireGuardDomain "${type}" exit 0 elif [[ "${warpStatus}" == "2" ]]; then echoContent yellow "Current status: disabled" echoContent yellow "Current status: not disabled" echoContent yellow "1.Disable" read -r -p "Please enter the domain name according to the above example:" domainList addWireGuardRoute "${type}" outboundTag "${domainList}" echoContent green " ---> Uninstall v2ray-agent script completed" elif [[ "${warpStatus}" == "3" ]]; then echoContent red "==============================================================" echoContent yellow "2.Open" echoContent yellow "1.View blocked domain names" echoContent yellow "2.Add domain name" read -r -p "Confirm settings? [y/n]:" warpOutStatus if [[ "${warpOutStatus}" == "y" ]]; then readConfigWarpReg if [[ "${coreInstallType}" == "1" ]]; then addXrayOutbound "wireguard_out_${type}" if [[ "${type}" == "IPv4" ]]; then removeXrayOutbound "wireguard_out_IPv6" elif [[ "${type}" == "IPv6" ]]; then removeXrayOutbound "wireguard_out_IPv4" fi removeXrayOutbound IPv4_out removeXrayOutbound IPv6_out removeXrayOutbound z_direct_outbound removeXrayOutbound blackhole_out removeXrayOutbound socks5_outbound rm ${configPath}09_routing.json >/dev/null 2>&1 fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig IPv4_out removeSingBoxConfig IPv6_out removeSingBoxConfig 01_direct_outbound removeSingBoxConfig wireguard_endpoints_IPv4_route removeSingBoxConfig wireguard_endpoints_IPv6_route removeSingBoxConfig IPv6_route removeSingBoxConfig socks5_02_inbound_route addSingBoxWireGuardEndpoints "${type}" addWireGuardRoute "${type}" outboundTag "" if [[ "${type}" == "IPv4" ]]; then removeSingBoxConfig wireguard_endpoints_IPv6 else removeSingBoxConfig wireguard_endpoints_IPv4 fi # outbound # addSingBoxOutbound "wireguard_out_${type}" "wireguard_out" fi echoContent green " ---> CDN modified successfully" else echoContent green " ---> Adding completed" exit 0 fi elif [[ "${warpStatus}" == "4" ]]; then if [[ "${coreInstallType}" == "1" ]]; then unInstallRouting "wireguard_out_${type}" outboundTag removeXrayOutbound "wireguard_out_${type}" addXrayOutbound "z_direct_outbound" fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig "wireguard_endpoints_${type}_route" removeSingBoxConfig "wireguard_endpoints_${type}" addSingBoxOutbound "01_direct_outbound" fi echoContent green " ---> Adding completed" else echoContent red " ---> Wrong selection, please select again" exit 0 fi reloadCore } # Diversion tool routingToolsMenu() { echoContent skyBlue "------------------------------------------------- ------" echoContent red "\n==============================================================" echoContent yellow "3.Block domestic domain names + IP" echoContent yellow "4.Delete blacklist/whitelist" echoContent yellow "5.Add blocked IP" echoContent yellow "6.Add domain whitelist" echoContent yellow "# Notes\n" echoContent yellow "1.Rules support predefined domain name list [https://github.com/v2fly/domain-list-community]" echoContent yellow "2.Rules support custom domain names" echoContent yellow "3.Input example: speedtest, facebook, cn, example.com" read -r -p "Please select:" selectType case ${selectType} in 1) warpRoutingReg 1 IPv4 ;; 2) warpRoutingReg 1 IPv6 ;; 3) ipv6Routing 1 ;; 4) socks5Routing ;; 5) dnsRouting 1 ;; # 6) # if [[ -n "${singBoxConfigPath}" ]]; then # fi # vmessWSRouting 1 # ;; 7) if [[ -n "${singBoxConfigPath}" ]]; then echoContent red "\n================================================ =================" fi sniRouting 1 ;; esac } # VMess+WS+TLS offload vmessWSRouting() { echoContent skyBlue "------------------------------------------------- ------" echoContent red "\n==============================================================" echoContent yellow "4.If the domain name exists in the predefined domain name list, use geosite:xx. If it does not exist, the entered domain name will be used by default." echoContent yellow "5.Add rules as incremental configuration and will not delete previously set content\n" echoContent yellow "Input example:1.1.1.1,8.8.8.8,1.1.1.0/24,2400:3200::/32\n" echoContent yellow "Input example:speedtest,openai,google.com\n" read -r -p "Please select:" selectType case ${selectType} in 1) setVMessWSRoutingOutbounds ;; 2) removeVMessWSRouting ;; esac } socks5Routing() { if [[ -z "${coreInstallType}" ]]; then echoContent red "================================================== ===============" exit 0 fi echoContent skyBlue "\nProgress$1/${totalProgress}: Update v2ray-agent script" echoContent red "\n==============================================================" echoContent red "================================================== ===============" echoContent yellow " ---> ${line} already exists, skip" echoContent yellow " ---> ${ipRuleValue} already exists, skip" echoContent yellow " ---> Abort installation" echoContent yellow "1.View the diverted domain name" echoContent yellow "2.Add domain name" echoContent yellow "3.Set WARP global" read -r -p "Please select:" selectType case ${selectType} in 1) socks5OutboundRoutingMenu ;; 2) socks5InboundRoutingMenu ;; 3) removeSocks5Routing ;; esac } socks5InboundRoutingMenu() { readInstallType echoContent skyBlue "wget -P /root -N --no-check-certificate https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh && chmod 700 /root/install.sh && /root/install.sh" echoContent red "\n==============================================================" echoContent yellow "4.Uninstall WARP distribution" echoContent yellow "# Notes" echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n" echoContent yellow "# Notes\n" read -r -p "Please select:" selectType case ${selectType} in 1) totalProgress=1 installSingBox 1 installSingBoxService 1 setSocks5Inbound setSocks5InboundRouting reloadCore socks5InboundRoutingMenu ;; 2) showSingBoxRoutingRules socks5_02_inbound_route socks5InboundRoutingMenu ;; 3) setSocks5InboundRouting addRules reloadCore socks5InboundRoutingMenu ;; 4) if [[ -f "${singBoxConfigPath}20_socks5_inbounds.json" ]]; then echoContent yellow "1.All diversion rules set will be deleted" echoContent green "\n ---> Update completed" echoContent green " ---> Current version: ${version}\n" echoContent green " ---> ufw closed successfully" else echoContent red "================================================== ===============" socks5InboundRoutingMenu fi ;; esac } socks5OutboundRoutingMenu() { echoContent skyBlue "\nFunction$1/${totalProgress}: View log" echoContent red "\n==============================================================" echoContent yellow "2.All outbound rules except WARP will be deleted" echoContent yellow "# Notes" echoContent yellow "# relies on third-party programs, please be aware of the risks" echoContent yellow "# Project address: https://github.com/badafans/warp-reg \n" read -r -p "Please select:" selectType case ${selectType} in 1) setSocks5Outbound setSocks5OutboundRouting reloadCore socks5OutboundRoutingMenu ;; 2) setSocks5Outbound setSocks5OutboundRoutingAll reloadCore socks5OutboundRoutingMenu ;; 3) showSingBoxRoutingRules socks5_01_outbound_route showXrayRoutingRules socks5_outbound socks5OutboundRoutingMenu ;; 4) setSocks5OutboundRouting addRules reloadCore socks5OutboundRoutingMenu ;; esac } setSocks5OutboundRoutingAll() { echoContent red "==============================================================" echoContent yellow " ---> Abort installation" echoContent yellow "1.View the diverted domain name" echoContent yellow "2.Add domain name" read -r -p "Confirm this setting? [y/n]:" socksOutStatus if [[ "${socksOutStatus}" == "y" ]]; then if [[ "${coreInstallType}" == "1" ]]; then removeXrayOutbound IPv4_out removeXrayOutbound IPv6_out removeXrayOutbound z_direct_outbound removeXrayOutbound blackhole_out removeXrayOutbound wireguard_out_IPv4 removeXrayOutbound wireguard_out_IPv6 rm ${configPath}09_routing.json >/dev/null 2>&1 fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig IPv4_out removeSingBoxConfig IPv6_out removeSingBoxConfig wireguard_endpoints_IPv4_route removeSingBoxConfig wireguard_endpoints_IPv6_route removeSingBoxConfig wireguard_endpoints_IPv4 removeSingBoxConfig wireguard_endpoints_IPv6 removeSingBoxConfig socks5_01_outbound_route removeSingBoxConfig 01_direct_outbound fi echoContent green " ---> firewalld closed successfully" fi } showSingBoxRoutingRules() { if [[ -n "${singBoxConfigPath}" ]]; then if [[ -f "${singBoxConfigPath}$1.json" ]]; then jq .route.rules "${singBoxConfigPath}$1.json" elif [[ "$1" == "socks5_01_outbound_route" && -f "${singBoxConfigPath}socks5_outbound.json" ]]; then echoContent yellow "3.Set WARP global" echoContent yellow "4.Uninstall WARP distribution" echoContent skyBlue "$(jq .outbounds[0] ${singBoxConfigPath}socks5_outbound.json)" elif [[ "$1" == "socks5_02_inbound_route" && -f "${singBoxConfigPath}20_socks5_inbounds.json" ]]; then echoContent yellow "# Notes" echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n" echoContent skyBlue "$(jq .outbounds[0] ${singBoxConfigPath}socks5_outbound.json)" fi fi } showXrayRoutingRules() { if [[ "${coreInstallType}" == "1" ]]; then if [[ -f "${configPath}09_routing.json" ]]; then jq ".routing.rules[]|select(.outboundTag==\"$1\")" "${configPath}09_routing.json" echoContent yellow "# Notes\n" echoContent yellow "1.All diversion rules set will be deleted" echoContent skyBlue "$(jq .outbounds[0].settings.servers[0] ${configPath}socks5_outbound.json)" elif [[ "$1" == "socks5_outbound" && -f "${configPath}socks5_outbound.json" ]]; then echoContent yellow "2.All outbound rules except WARP [third party] will be deleted" echoContent yellow "1.WARP diversion [Third-party IPv4]" echoContent skyBlue "$(jq .outbounds[0].settings.servers[0] ${configPath}socks5_outbound.json)" fi fi } removeSocks5Routing() { echoContent skyBlue "\nFunction 1/${totalProgress}: IPv6 offload" echoContent red "\n==============================================================" echoContent yellow "2.WARP diversion [Third-party IPv6]" echoContent yellow "3.IPv6 offload" echoContent yellow "4.Any door diversion" read -r -p "Select:" unInstallSocks5RoutingStatus if [[ "${unInstallSocks5RoutingStatus}" == "1" ]]; then if [[ "${coreInstallType}" == "1" ]]; then removeXrayOutbound socks5_outbound unInstallRouting socks5_outbound outboundTag addXrayOutbound z_direct_outbound fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig socks5_outbound removeSingBoxConfig socks5_01_outbound_route addSingBoxOutbound 01_direct_outbound fi elif [[ "${unInstallSocks5RoutingStatus}" == "2" ]]; then removeSingBoxConfig 20_socks5_inbounds removeSingBoxConfig socks5_02_inbound_route removeSingBoxConfig sniff_socks5_inbound removeSingBoxConfig "strategy_ipv4_only_socks5_inbound" removeSingBoxConfig "strategy_ipv6_only_socks5_inbound" handleSingBox stop elif [[ "${unInstallSocks5RoutingStatus}" == "3" ]]; then if [[ "${coreInstallType}" == "1" ]]; then removeXrayOutbound socks5_outbound unInstallRouting socks5_outbound outboundTag addXrayOutbound z_direct_outbound fi if [[ -n "${singBoxConfigPath}" ]]; then removeSingBoxConfig socks5_outbound removeSingBoxConfig socks5_01_outbound_route removeSingBoxConfig 20_socks5_inbounds removeSingBoxConfig socks5_02_inbound_route removeSingBoxConfig sniff_socks5_inbound removeSingBoxConfig "strategy_ipv4_only_socks5_inbound" removeSingBoxConfig "strategy_ipv6_only_socks5_inbound" addSingBoxOutbound 01_direct_outbound fi handleSingBox stop else echoContent red " ---> Available types are not installed" exit 0 fi echoContent green "The mature works of [ylx2016] used for BBR and DD scripts, the address [https://github.com/ylx2016/Linux-NetSpeed], please be familiar with it" reloadCore } setSocks5Inbound() { echoContent yellow "5.DNS divert" echoContent skyBlue "\nFunction 1/${totalProgress}: bt download management" echo mapfile -t result < <(initSingBoxPort "${singBoxSocks5Port}") echoContent green "The shortcut is created successfully, you can execute [vasma] to reopen the script" echoContent green " ---> Added successfully" echoContent yellow "6.VMess+WS+TLS offload" read -r -p 'UUID:' socks5RoutingUUID if [[ -z "${socks5RoutingUUID}" ]]; then if [[ "${coreInstallType}" == "1" ]]; then socks5RoutingUUID=$(/etc/v2ray-agent/xray/xray uuid) elif [[ -n "${singBoxConfigPath}" ]]; then socks5RoutingUUID=$(/etc/v2ray-agent/sing-box/sing-box generate uuid) fi fi echo echoContent green " ---> IPv6 global outbound setting successful" echoContent green " ---> Abandon settings" echoContent yellow "7.SNI reverse proxy offload" echoContent yellow "1.Any door floor machine unlocks streaming media" echoContent yellow "2.DNS unlock streaming media" echoContent yellow "2.IPv6" read -r -p 'IP type:' socks5InboundDomainStrategyStatus local domainStrategy= if [[ -z "${socks5InboundDomainStrategyStatus}" || "${socks5InboundDomainStrategyStatus}" == "1" ]]; then domainStrategy="ipv4_only" elif [[ "${socks5InboundDomainStrategyStatus}" == "2" ]]; then domainStrategy="ipv6_only" else echoContent red " ---> Wrong selection" exit 0 fi cat </etc/v2ray-agent/sing-box/conf/config/20_socks5_inbounds.json { "inbounds":[ { "type": "socks", "listen":"::", "listen_port":${result[-1]}, "tag":"socks5_inbound", "users":[ { "username": "${socks5RoutingUUID}", "password": "${socks5RoutingUUID}" } ] } ] } EOF setStrategyRouting socks5_inbound "${domainStrategy}" } initSingBoxRules() { local domainRules=[] local ruleSet=[] while read -r line; do local normalizedLine= normalizedLine=$(echo "${line}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') if isDomainFormat "${normalizedLine}"; then local escapedDomain= escapedDomain=${normalizedLine//./\\.} domainRules=$(echo "${domainRules}" | jq -r --arg reg ".*${escapedDomain}.*" '. += [$reg]') else local matchedRuleName matchedRuleName=$(getDLCGeositeName "${normalizedLine}" "/etc/v2ray-agent/sing-box") if [[ -n "${matchedRuleName}" ]]; then ruleSet=$(echo "${ruleSet}" | jq -r ". += [{\"tag\":\"${matchedRuleName}_$2\",\"type\":\"remote\",\"format\":\"binary\",\"url\":\"https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-${matchedRuleName}.srs\",\"http_client\":\"rule_set_http\"}]") else domainRules=$(echo "${domainRules}" | jq -r --arg reg "^([a-zA-Z0-9_-]+\\.)*${normalizedLine//./\\.}" '. += [$reg]') fi fi done < <(echo "$1" | tr ',' '\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\n') echo "{ \"domainRules\":${domainRules},\"ruleSet\":${ruleSet}}" } setSocks5InboundRouting() { singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/ if [[ "$1" == "addRules" && ! -f "${singBoxConfigPath}socks5_02_inbound_route.json" && ! -f "${configPath}09_routing.json" ]]; then echoContent red " ---> UUID cannot be repeated" echoContent red " ---> email cannot be repeated" exit 0 fi local socks5InboundRoutingIPs= if [[ "$1" == "addRules" ]]; then socks5InboundRoutingIPs=$(jq .route.rules[0].source_ip_cidr "${singBoxConfigPath}socks5_02_inbound_route.json") else echoContent red "==============================================================" echoContent skyBlue "\nProgress$1/${totalProgress}: Domain name blacklist" read -r -p "IP:" socks5InboundRoutingIPs if [[ -z "${socks5InboundRoutingIPs}" ]]; then echoContent red " ---> Incorrect input, please re-enter" exit 0 fi socks5InboundRoutingIPs=$(echo "\"${socks5InboundRoutingIPs}"\" | jq -c '.|split(",")') fi echoContent red "==============================================================" echoContent skyBlue "\nProgress$1/${totalProgress}: WARP offload" echoContent yellow "3.VMess+WS+TLS to unlock streaming media" echoContent yellow "# Notes" echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n" echoContent yellow "1.Add outbound" read -r -p "Allow all websites? Select [y/n]:" socks5InboundRoutingDomainStatus if [[ "${socks5InboundRoutingDomainStatus}" == "y" ]]; then addSingBoxRouteRule "01_direct_outbound" "" "socks5_02_inbound_route" local route= route=$(jq ".route.rules[0].inbound = [\"socks5_inbound\"]" "${singBoxConfigPath}socks5_02_inbound_route.json") route=$(echo "${route}" | jq ".route.rules[0].source_ip_cidr=${socks5InboundRoutingIPs}") echo "${route}" | jq . >"${singBoxConfigPath}socks5_02_inbound_route.json" addSingBoxOutbound block addSingBoxOutbound "01_direct_outbound" else echoContent yellow "2.Add inbound" read -r -p "Domain:" socks5InboundRoutingDomain if [[ -z "${socks5InboundRoutingDomain}" ]]; then echoContent red " ---> Incorrect input, please re-enter" exit 0 fi addSingBoxRouteRule "01_direct_outbound" "${socks5InboundRoutingDomain}" "socks5_02_inbound_route" local route= route=$(jq ".route.rules[0].inbound = [\"socks5_inbound\"]" "${singBoxConfigPath}socks5_02_inbound_route.json") route=$(echo "${route}" | jq ".route.rules[0].source_ip_cidr=${socks5InboundRoutingIPs}") echo "${route}" | jq . >"${singBoxConfigPath}socks5_02_inbound_route.json" addSingBoxOutbound block addSingBoxOutbound "01_direct_outbound" fi } setSniffRouting() { local singBoxDNSConfigPath="/etc/v2ray-agent/sing-box/conf/config/dns.json" if [[ -f "${singBoxDNSConfigPath}" ]]; then jq ' .dns.servers = (.dns.servers // []) | if any(.dns.servers[]?; .tag == "local") then . elif any(.dns.servers[]?; .type == "local" and ((.tag // "") == "")) then .dns.servers |= map(if .type == "local" and ((.tag // "") == "") then .tag = "local" else . end) else .dns.servers += [{"tag": "local", "type": "local"}] end ' "${singBoxDNSConfigPath}" >"${singBoxDNSConfigPath}.tmp" && mv "${singBoxDNSConfigPath}.tmp" "${singBoxDNSConfigPath}" else cat <"${singBoxDNSConfigPath}" { "dns": { "servers": [ { "tag": "local", "type": "local" } ] } } EOF fi cat <"/etc/v2ray-agent/sing-box/conf/config/sniff.json" { "route":{ "default_domain_resolver": "local", "rules":[ { "action": "sniff", "timeout": "1s" }, { "protocol": "dns", "action": "hijack-dns" } ] } } EOF } setStrategyRouting() { local tag=$1 local strategy=$2 cat <"/etc/v2ray-agent/sing-box/conf/config/strategy_${strategy}_${tag}.json" { "route":{ "rules":[ { "inbound": "${tag}", "action": "resolve", "strategy": "${strategy}" } ] } } EOF } setSocks5Outbound() { echoContent yellow "3.Uninstall" echo read -r -p "Enter the landing server IP address:" socks5RoutingOutboundIP if [[ -z "${socks5RoutingOutboundIP}" ]]; then echoContent red " ---> Wrong selection" exit 0 fi echo read -r -p "Enter the landing server port:" socks5RoutingOutboundPort if [[ -z "${socks5RoutingOutboundPort}" ]]; then echoContent red " ---> Wrong selection" exit 0 fi echo read -r -p "Enter username:" socks5RoutingOutboundUserName if [[ -z "${socks5RoutingOutboundUserName}" ]]; then echoContent red "\n================================================ =================" exit 0 fi echo read -r -p "Enter password:" socks5RoutingOutboundPassword if [[ -z "${socks5RoutingOutboundPassword}" ]]; then echoContent red "================================================== ===============" exit 0 fi echo if [[ -n "${singBoxConfigPath}" ]]; then cat <"${singBoxConfigPath}socks5_outbound.json" { "outbounds":[ { "type": "socks", "tag":"socks5_outbound", "server": "${socks5RoutingOutboundIP}", "server_port": ${socks5RoutingOutboundPort}, "version": "5", "username":"${socks5RoutingOutboundUserName}", "password":"${socks5RoutingOutboundPassword}" } ] } EOF fi if [[ "${coreInstallType}" == "1" ]]; then addXrayOutbound socks5_outbound fi } setSocks5OutboundRouting() { if [[ "$1" == "addRules" && ! -f "${singBoxConfigPath}socks5_01_outbound_route.json" && ! -f "${configPath}09_routing.json" ]]; then echoContent red " ---> The installation directory is not detected, please execute the script to install the content" exit 0 fi echoContent red "==============================================================" echoContent skyBlue "\nProgress$1/${totalProgress}: WARP offload [third party]" echoContent yellow "# Notes" echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n" echoContent yellow "1.Add outbound" echoContent yellow "2.Uninstall" echoContent yellow "Input example:netflix,openai\n" read -r -p "Domain:" socks5RoutingOutboundDomain if [[ -z "${socks5RoutingOutboundDomain}" ]]; then echoContent red "\n================================================ =================" exit 0 fi addSingBoxRouteRule "socks5_outbound" "${socks5RoutingOutboundDomain}" "socks5_01_outbound_route" addSingBoxOutbound "01_direct_outbound" if [[ "${coreInstallType}" == "1" ]]; then unInstallRouting "socks5_outbound" "outboundTag" local domainRules=[] while read -r line; do if echo "${routingRule}" | grep -q "${line}"; then echoContent yellow "Input example:netflix,openai\n" else local matchedRuleValue matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray") domainRules=$(echo "${domainRules}" | jq -r --arg rule "${matchedRuleValue}" '. += [$rule]') fi done < <(echo "${socks5RoutingOutboundDomain}" | tr ',' '\n') if [[ ! -f "${configPath}09_routing.json" ]]; then cat <${configPath}09_routing.json { "routing":{ "rules": [] } } EOF fi routing=$(jq -r ".routing.rules += [{\"type\": \"field\",\"domain\": ${domainRules},\"outboundTag\": \"socks5_outbound\"}]" ${configPath}09_routing.json) echo "${routing}" | jq . >${configPath}09_routing.json fi } # Set VMess+WS+TLS [outbound only] setVMessWSRoutingOutbounds() { read -r -p "Please enter the address of VMess+WS+TLS:" setVMessWSTLSAddress echoContent red "==============================================================" echoContent yellow "ip entry example:1.1.1.1,1.1.1.2" read -r -p "Please enter the domain name according to the above example:" domainList if [[ -z ${domainList} ]]; then echoContent red "================================================== ===============" setVMessWSRoutingOutbounds fi if [[ -n "${setVMessWSTLSAddress}" ]]; then removeXrayOutbound VMess-out echo read -r -p "Please enter the port of VMess+WS+TLS:" setVMessWSTLSPort echo if [[ -z "${setVMessWSTLSPort}" ]]; then echoContent red " ---> does not support ipv6" fi read -r -p "Please enter the UUID of VMess+WS+TLS:" setVMessWSTLSUUID echo if [[ -z "${setVMessWSTLSUUID}" ]]; then echoContent red " ---> Not installed, please use script to install" fi read -r -p "Please enter the Path of VMess+WS+TLS:" setVMessWSTLSPath echo if [[ -z "${setVMessWSTLSPath}" ]]; then echoContent red "\n================================================ ============ =====" elif ! echo "${setVMessWSTLSPath}" | grep -q "/"; then setVMessWSTLSPath="/${setVMessWSTLSPath}" fi addXrayOutbound "VMess-out" addXrayRouting VMess-out outboundTag "${domainList}" reloadCore echoContent green " ---> IPv6 offload uninstall successful" exit 0 fi echoContent red "================================================== ===============" setVMessWSRoutingOutbounds } # Remove VMess+WS+TLS shunt removeVMessWSRouting() { removeXrayOutbound VMess-out unInstallRouting VMess-out outboundTag reloadCore echoContent green " ---> BT download disabled successfully" } # Restart core reloadCore() { readInstallType if [[ "${coreInstallType}" == "1" ]]; then handleXray stop handleXray start fi if echo "${currentInstallProtocolType}" | grep -q ",20," || [[ "${coreInstallType}" == "2" || -n "${singBoxConfigPath}" ]]; then handleSingBox stop handleSingBox start fi } # dns divert dnsRouting() { if [[ -z "${configPath}" ]]; then echoContent red "================================================== ===============" menu exit 0 fi echoContent skyBlue "\nFunction 1/${totalProgress}: Diversion tool" echoContent red "\n==============================================================" echoContent yellow "The domain name below must be consistent with the outbound vps" echoContent yellow "Example of domain name entry: netflix,openai\n" echoContent yellow "# Notes" echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n" read -r -p "Please select:" selectType case ${selectType} in 1) setUnlockDNS ;; 2) removeUnlockDNS ;; esac } # SNI reverse proxy offload sniRouting() { if [[ -z "${configPath}" ]]; then echoContent red "================================================== ===============" menu exit 0 fi echoContent skyBlue "\nFunction 1/${totalProgress}: Streaming Media Toolbox" echoContent red "\n==============================================================" echoContent yellow "1.Add" echoContent yellow "2.Uninstall" echoContent yellow "# Notes" echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n" echoContent yellow "1.Add" read -r -p "Please select:" selectType case ${selectType} in 1) setUnlockSNI ;; 2) removeUnlockSNI ;; esac } # Set up SNI offloading setUnlockSNI() { read -r -p "Please enter the SNI IP of the offload:" setSNIP if [[ -n ${setSNIP} ]]; then echoContent red "==============================================================" if [[ "${coreInstallType}" == 1 ]]; then echoContent yellow "2.Uninstall" read -r -p "Enter domains using the example above:" xrayDomainList local hosts={} while read -r domain; do local matchedRuleValue matchedRuleValue=$(getDLCMatchedRuleValue "${domain}" "/etc/v2ray-agent/xray") hosts=$(echo "${hosts}" | jq -r --arg key "${matchedRuleValue}" --arg value "${setSNIP}" '. + {($key):$value}') done < <(echo "${xrayDomainList}" | tr ',' '\n') cat <${configPath}11_dns.json { "dns": { "hosts":${hosts}, "servers": [ "8.8.8.8", "1.1.1.1" ] } } EOF fi if [[ -n "${singBoxConfigPath}" ]]; then echoContent yellow "Input example: netflix, disney, hulu" read -r -p "Enter domains using the example above:" singboxDomainList addSingBoxDNSConfig "${setSNIP}" "${singboxDomainList}" "predefined" fi echoContent yellow "Input example: netflix, disney, hulu" reloadCore else echoContent red " ---> Wrong selection" fi exit 0 } addXrayDNSConfig() { local ip=$1 local domainList=$2 local domains=[] while read -r line; do local matchedRuleValue matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray") domains=$(echo "${domains}" | jq -r --arg rule "${matchedRuleValue}" '. += [$rule]') done < <(echo "${domainList}" | tr ',' '\n') if [[ "${coreInstallType}" == "1" ]]; then cat <${configPath}11_dns.json { "dns": { "servers": [ { "address": "${ip}", "port": 53, "domains": ${domains} }, "localhost" ] } } EOF fi } addSingBoxDNSConfig() { local ip=$1 local domainList=$2 local actionType=$3 local rules= rules=$(initSingBoxRules "${domainList}" "dns") local domainRules= domainRules=$(echo "${rules}" | jq .domainRules) local ruleSet= ruleSet=$(echo "${rules}" | jq .ruleSet) local ruleSetTag=[] if [[ "$(echo "${ruleSet}" | jq '.|length')" != "0" ]]; then ruleSetTag=$(echo "${ruleSet}" | jq '.|map(.tag)') fi if [[ -n "${singBoxConfigPath}" ]]; then if [[ "${actionType}" == "predefined" ]]; then local predefined={} while read -r line; do predefined=$(echo "${predefined}" | jq ".\"${line}\"=\"${ip}\"") done < <(echo "${domainList}" | tr ',' '\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\n') cat <"${singBoxConfigPath}dns.json" { "dns": { "servers": [ { "tag": "local", "type": "local" }, { "tag": "hosts", "type": "hosts", "predefined": ${predefined} } ], "rules": [ { "domain_regex":${domainRules}, "server":"hosts" } ] } } EOF else cat <"${singBoxConfigPath}dns.json" { "dns": { "servers": [ { "tag": "local", "type": "local" }, { "tag": "dnsRouting", "type": "udp", "server": "${ip}" } ], "rules": [ { "rule_set": ${ruleSetTag}, "domain_regex": ${domainRules}, "server":"dnsRouting" } ] }, "route":{ "rule_set":${ruleSet} } } EOF fi fi } # Set dns setUnlockDNS() { read -r -p "Please enter the diverted DNS:" setDNS if [[ -n ${setDNS} ]]; then echoContent red "==============================================================" echoContent yellow "Please enter 1 for the default scheme. The default scheme includes the following content" read -r -p "Please enter the domain name according to the above example:" domainList if [[ "${coreInstallType}" == "1" ]]; then addXrayDNSConfig "${setDNS}" "${domainList}" fi if [[ -n "${singBoxConfigPath}" ]]; then addSingBoxOutbound 01_direct_outbound addSingBoxDNSConfig "${setDNS}" "${domainList}" fi reloadCore echoContent yellow "netflix,bahamut,hulu,hbo,disney,bbc,4chan,fox,abema,dmm,niconico,pixiv,bilibili,viu" echoContent yellow "\n ---> If you still can't watch, you can try the following two solutions" echoContent yellow "1.Restart vps" else echoContent red " ---> Not installed, please use script to install" fi exit 0 } # Remove DNS offloading removeUnlockDNS() { if [[ "${coreInstallType}" == "1" && -f "${configPath}11_dns.json" ]]; then cat <${configPath}11_dns.json { "dns": { "servers": [ "localhost" ] } } EOF fi if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}dns.json" ]]; then cat <${singBoxConfigPath}dns.json { "dns": { "servers":[ { "tag":"local", "type":"local" } ] } } EOF fi reloadCore echoContent green " ---> BT download opened successfully" exit 0 } # Remove SNI shunt removeUnlockSNI() { if [[ "${coreInstallType}" == 1 ]]; then cat <${configPath}11_dns.json { "dns": { "servers": [ "localhost" ] } } EOF fi if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}dns.json" ]]; then cat <${singBoxConfigPath}dns.json { "dns": { "servers":[ { "type":"local" } ] } } EOF fi reloadCore echoContent green " ---> Added successfully" exit 0 } customSingBoxInstall() { echoContent skyBlue "\nFunction 1/${totalProgress}: any door diversion" echoContent yellow "0.VLESS+Vision+TCP" echoContent yellow "2.After uninstalling dns unlocking, modify the local [/etc/resolv.conf] DNS settings and restart vps\n" echoContent yellow "VLESS is prefixed and 0 is installed by default. If you only need to install 0, just select 0" echoContent yellow "0.VLESS+TLS_Vision+TCP" echoContent yellow "6.Hysteria2" echoContent yellow "7.VLESS+Reality+Vision" echoContent yellow "8.VLESS+Reality+gRPC" echoContent yellow "9.Tuic" echoContent yellow "10.Naive" echoContent yellow "11.VMess+TLS+HTTPUpgrade" echoContent yellow "13.anytls" read -r -p "Please select [multiple selection], [for example: 123]:" selectCustomInstallType echoContent skyBlue "--------------------------------------------------------------" if echo "${selectCustomInstallType}" | grep -q ","; then echoContent red "\n================================================ =================" exit 0 fi if [[ "${selectCustomInstallType}" != "10" ]] && [[ "${selectCustomInstallType}" != "11" ]] && [[ "${selectCustomInstallType}" != "13" ]] && ((${#selectCustomInstallType} >= 2)) && ! echo "${selectCustomInstallType}" | grep -q ","; then echoContent red "================================================== ===============" exit 0 fi if [[ "${selectCustomInstallType: -1}" != "," ]]; then selectCustomInstallType="${selectCustomInstallType}," fi if [[ "${selectCustomInstallType:0:1}" != "," ]]; then selectCustomInstallType=",${selectCustomInstallType}," fi if [[ "${selectCustomInstallType//,/}" =~ ^[0-9]+$ ]]; then readLastInstallationConfig unInstallSubscribe totalProgress=9 installTools 1 if echo "${selectCustomInstallType}" | grep -q -E ",0,|,1,|,3,|,4,|,6,|,9,|,10,|,11,|,13,"; then # Apply for tls initTLSNginxConfig 2 # handleNginx start installTLS 3 handleNginx stop fi installSingBox 4 installSingBoxService 5 initSingBoxConfig custom 6 cleanUp xrayDel installCronTLS 7 handleSingBox stop handleSingBox start handleNginx stop handleNginx start checkGFWStatue 8 showAccounts 9 else echoContent red " ---> Wrong selection" customSingBoxInstall fi } installXrayReality() { selectCustomInstallType=",7," readLastInstallationConfig unInstallSubscribe totalProgress=6 installTools 1 handleNginx stop installXray 2 false installXrayService 3 initXrayConfig custom 4 cleanUp singBoxDel handleXray stop handleXray start checkGFWStatue 5 showAccounts 6 } installSingBoxReality() { selectCustomInstallType=",7," readLastInstallationConfig unInstallSubscribe totalProgress=6 installTools 1 installSingBox 2 installSingBoxService 3 initSingBoxConfig custom 4 cleanUp xrayDel handleSingBox stop handleSingBox start checkGFWStatue 5 showAccounts 6 } # Xray-core personalized installation customXrayInstall() { echoContent skyBlue "\nFunction 1/${totalProgress}: VMess+WS+TLS offload" echoContent yellow "1.VLESS+TLS+WS[CDN]" echoContent yellow "2.Trojan+TLS+gRPC[CDN]" echoContent yellow "3.VMess+TLS+WS[CDN]" echoContent yellow "4.Trojan+TLS" echoContent yellow "5.VLESS+TLS+gRPC[CDN]" echoContent yellow "VLESS is prefixed and 0 is installed by default. If you only need to install 0, just select 0" # echoContent yellow "8.VLESS+Reality+gRPC" echoContent yellow "0.VLESS+TLS_Vision+TCP[recommended]" read -r -p "Please select [multiple selection], [for example: 123]:" selectCustomInstallType echoContent skyBlue "--------------------------------------------------------------" if echo "${selectCustomInstallType}" | grep -q ","; then echoContent red " ---> Not installed, please use script to install" exit 0 fi if [[ "${selectCustomInstallType}" != "12" ]] && ((${#selectCustomInstallType} >= 2)) && ! echo "${selectCustomInstallType}" | grep -q ","; then echoContent red "\n================================================ =================" exit 0 fi if echo "${selectCustomInstallType}" | grep -qE '^(7|7,12|12)$'; then selectCustomInstallType=",${selectCustomInstallType}," else if ! echo "${selectCustomInstallType}" | grep -q "0,"; then selectCustomInstallType=",0,${selectCustomInstallType}," else selectCustomInstallType=",${selectCustomInstallType}," fi fi if [[ "${selectCustomInstallType:0:1}" != "," ]]; then selectCustomInstallType=",${selectCustomInstallType}," fi if [[ "${selectCustomInstallType//,/}" =~ ^[0-7]+$ ]]; then readLastInstallationConfig unInstallSubscribe # checkBTPanel # check1Panel totalProgress=12 installTools 1 if [[ -n "${btDomain}" ]]; then echoContent skyBlue "\nFunction 1/${totalProgress}: Add inbound at any door" handleXray stop if [[ "${selectCustomInstallType}" != ",7," ]]; then customPortFunction fi else if ! echo "${selectCustomInstallType}" | grep -qE '^(,7,|,7,12,|,12,)$'; then # Apply for tls initTLSNginxConfig 2 handleXray stop installTLS 3 else echoContent skyBlue "\nFunction 1/${totalProgress}: DNS offloading" fi fi handleNginx stop if echo "${selectCustomInstallType}" | grep -qE ",1,|,2,|,3,|,5,|,12,"; then randomPathFunction 4 fi if [[ -n "${btDomain}" ]]; then echoContent skyBlue "\nFunction 1/${totalProgress}: SNI reverse proxy offload" else nginxBlog 6 fi if ! echo "${selectCustomInstallType}" | grep -qE '^(,7,|,7,12,|,12,)$'; then updateRedirectNginxConf handleNginx start fi # Install Xray installXray 7 false installXrayService 8 initXrayConfig custom 9 cleanUp singBoxDel if ! echo "${selectCustomInstallType}" | grep -qE '^(,7,|,7,12,|,12,)$'; then installCronTLS 10 fi handleXray stop handleXray start # Generate account checkGFWStatue 11 showAccounts 12 else echoContent red "================================================== ===============" customXrayInstall fi } # Select core installation---v2ray-core, xray-core selectCoreInstall() { echoContent skyBlue "\n========================Personalized installation================== ==========" echoContent red "\n==============================================================" echoContent yellow "1.Xray-core" echoContent yellow "2.sing-box" echoContent red "==============================================================" read -r -p "Please select:" selectCoreType case ${selectCoreType} in 1) if [[ "${selectInstallType}" == "1" ]]; then xrayCoreInstall elif [[ "${selectInstallType}" == "2" ]]; then customXrayInstall elif [[ "${selectInstallType}" == "3" ]]; then installXrayReality fi ;; 2) if [[ "${selectInstallType}" == "1" ]]; then singBoxInstall elif [[ "${selectInstallType}" == "2" ]]; then customSingBoxInstall elif [[ "${selectInstallType}" == "3" ]]; then installSingBoxReality fi ;; *) echoContent red "================================================== ===============" selectCoreInstall ;; esac } # xray-core installation xrayCoreInstall() { readLastInstallationConfig unInstallSubscribe # checkBTPanel # check1Panel selectCustomInstallType= totalProgress=12 installTools 2 if [[ -n "${btDomain}" ]]; then echoContent skyBlue "------------------------------------------------- ---------------" handleXray stop customPortFunction else # Apply for tls initTLSNginxConfig 3 handleXray stop # handleNginx start installTLS 4 fi handleNginx stop randomPathFunction 5 # Install Xray installXray 6 false installXrayService 7 initXrayConfig all 8 cleanUp singBoxDel installCronTLS 9 if [[ -n "${btDomain}" ]]; then echoContent skyBlue "\n========================Personalized installation================== ==========" else nginxBlog 10 fi updateRedirectNginxConf handleXray stop sleep 2 handleXray start handleNginx start checkGFWStatue 11 showAccounts 12 } singBoxInstall() { readLastInstallationConfig unInstallSubscribe # checkBTPanel # check1Panel selectCustomInstallType= totalProgress=8 installTools 2 if [[ -n "${btDomain}" ]]; then echoContent skyBlue "------------------------------------------------- --------- ------" handleXray stop customPortFunction else initTLSNginxConfig 3 handleXray stop installTLS 4 fi handleNginx stop installSingBox 5 installSingBoxService 6 initSingBoxConfig all 7 cleanUp xrayDel installCronTLS 8 handleSingBox stop handleSingBox start handleNginx stop handleNginx start showAccounts 9 } # Core Management coreVersionManageMenu() { if [[ -z "${coreInstallType}" ]]; then echoContent red " ---> ip cannot be empty" menu exit 0 fi echoContent skyBlue "\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS" echoContent red "\n==============================================================" echoContent yellow "1.Xray-core" echoContent yellow "2.sing-box" echoContent red "==============================================================" read -r -p "Enter selection:" selectCore if [[ "${selectCore}" == "1" ]]; then xrayVersionManageMenu 1 elif [[ "${selectCore}" == "2" ]]; then singBoxVersionManageMenu 1 fi } # Scheduled task check cronFunction() { if [[ "${cronName}" == "RenewTLS" ]]; then renewalTLS exit 0 elif [[ "${cronName}" == "UpdateGeo" ]]; then updateGeoSite >>/etc/v2ray-agent/crontab_updateGeoSite.log echoContent green " ---> geo update date: $(date "+%F %H:%M:%S")" >>/etc/v2ray-agent/crontab_updateGeoSite.log exit 0 fi } #Account management manageAccount() { echoContent skyBlue "\nProgress 6/${totalProgress}: Pagoda panel detected, skipping disguised website" if [[ -z "${configPath}" ]]; then echoContent red " ---> domain cannot be empty" exit 0 fi echoContent red "\n==============================================================" echoContent yellow "1.VLESS+TLS+WS[CDN]" echoContent yellow "2.Trojan+TLS+gRPC[CDN]" echoContent yellow "3.VMess+TLS+WS[CDN]" echoContent yellow "4.Trojan+TLS" echoContent yellow "5.VLESS+TLS+gRPC[CDN]" echoContent yellow "7.VLESS+Reality+uTLS+Vision[recommended]" echoContent yellow "1.Xray-core" echoContent red "==============================================================" read -r -p "Please enter:" manageAccountStatus if [[ "${manageAccountStatus}" == "1" ]]; then showAccounts 1 elif [[ "${manageAccountStatus}" == "2" ]]; then subscribe elif [[ "${manageAccountStatus}" == "3" ]]; then addSubscribeMenu 1 elif [[ "${manageAccountStatus}" == "4" ]]; then addUser elif [[ "${manageAccountStatus}" == "5" ]]; then removeUser else echoContent red " ---> Wrong selection" fi } installSubscribe() { readNginxSubscribe local nginxSubscribeListen= local nginxSubscribeSSL= local serverName= local SSLType= local listenIPv6= if [[ -z "${subscribePort}" ]]; then nginxVersion=$(nginx -v 2>&1) if echo "${nginxVersion}" | grep -q "not found" || [[ -z "${nginxVersion}" ]]; then echoContent yellow "2.v2ray-core" read -r -p "Install [y/n]?" installNginxStatus if [[ "${installNginxStatus}" == "y" ]]; then installNginxTools else echoContent red " ---> Parameter error" exit 0 fi fi echoContent yellow "# Only delete VLESS Reality related configurations, other content will not be deleted." mapfile -t result < <(initSingBoxPort "${subscribePort}") echo echoContent yellow "# If you need to uninstall other content, please uninstall the script function" nginxBlog echo local httpSubscribeStatus= if ! echo "${selectCustomInstallType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,|,11,|,13," && ! echo "${currentInstallProtocolType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,|,11,|,13," && [[ -z "${domain}" ]]; then httpSubscribeStatus=true fi if [[ "${httpSubscribeStatus}" == "true" ]]; then echoContent yellow "# You can customize email and uuid when adding a single user" echo read -r -p "Use HTTP subscription [y/n]?" addNginxSubscribeStatus echo if [[ "${addNginxSubscribeStatus}" != "y" ]]; then echoContent yellow "# If Hysteria or Tuic is installed, the account will be added to the corresponding type at the same time\n" exit fi else local subscribeServerName= if [[ -n "${currentHost}" ]]; then subscribeServerName="${currentHost}" else subscribeServerName="${domain}" fi SSLType="ssl" serverName="server_name ${subscribeServerName};" nginxSubscribeSSL="ssl_certificate /etc/v2ray-agent/tls/${subscribeServerName}.crt;ssl_certificate_key /etc/v2ray-agent/tls/${subscribeServerName}.key;" fi if [[ -n "$(curl --connect-timeout 2 -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2)" ]]; then listenIPv6="listen [::]:${result[-1]} ${SSLType};" fi if echo "${nginxVersion}" | grep -q "1.25" && [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $3}') -gt 0 ]] || [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $2}') -gt 25 ]]; then nginxSubscribeListen="listen ${result[-1]} ${SSLType} so_keepalive=on;http2 on;${listenIPv6}" else nginxSubscribeListen="listen ${result[-1]} ${SSLType} so_keepalive=on;${listenIPv6}" fi cat <${nginxConfigPath}subscribe.conf server { ${nginxSubscribeListen} ${serverName} ${nginxSubscribeSSL} ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers on; resolver 1.1.1.1 valid=60s; resolver_timeout 2s; client_max_body_size 100m; root ${nginxStaticPath}; location ~ ^/s/(clashMeta|default|clashMetaProfiles|sing-box|sing-box_profiles)/(.*) { default_type 'text/plain; charset=utf-8'; alias /etc/v2ray-agent/subscribe/\$1/\$2; } location / { } } EOF bootStartup nginx handleNginx stop handleNginx start fi if [[ -z $(pgrep -f "nginx") ]]; then handleNginx start fi } unInstallSubscribe() { rm -rf ${nginxConfigPath}subscribe.conf >/dev/null 2>&1 } #Add subscription addSubscribeMenu() { echoContent skyBlue "\nFunction 1/${totalProgress}: Select core installation" echoContent yellow "1.Check account" echoContent yellow "2.View subscription" echoContent red "==============================================================" read -r -p "Please select:" addSubscribeStatus if [[ "${addSubscribeStatus}" == "1" ]]; then addOtherSubscribe elif [[ "${addSubscribeStatus}" == "2" ]]; then if [[ ! -f "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" ]]; then echoContent green " ---> Domestic domain name + IP blocked successfully" exit 0 fi grep -v '^$' "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" | awk '{print NR""":"$0}' read -r -p "Select the subscription number to delete [single selection only]:" delSubscribeIndex if [[ -z "${delSubscribeIndex}" ]]; then echoContent green " ---> Domain blacklist/whitelist deleted successfully" exit 0 fi sed -i "$((delSubscribeIndex))d" "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" >/dev/null 2>&1 echoContent green " ---> Blocked IP added successfully" subscribe fi } # Add other machines to clashMeta subscription addOtherSubscribe() { echoContent yellow "3.Add subscription" echoContent yellow "4.Add user" echoContent skyBlue "\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS" read -r -p "Please enter the domain name, port and machine alias:" remoteSubscribeUrl if [[ -z "${remoteSubscribeUrl}" ]]; then echoContent red " ---> Parameter error" addOtherSubscribe elif ! echo "${remoteSubscribeUrl}" | grep -q ":"; then echoContent red "==============================================================" else if [[ -f "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" ]] && grep -q "${remoteSubscribeUrl}" /etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl; then echoContent red "\n================================================ =================" exit 0 fi echo read -r -p "Is this an HTTP subscription? [y/n]" httpSubscribeStatus if [[ "${httpSubscribeStatus}" == "y" ]]; then remoteSubscribeUrl="${remoteSubscribeUrl}:http" fi echo "${remoteSubscribeUrl}" >>/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl subscribe fi } # clashMeta configuration file clashMetaConfig() { local url=$1 local id=$2 cat <"/etc/v2ray-agent/subscribe/clashMetaProfiles/${id}" log-level: debug mode: rule ipv6: true mixed-port: 7890 allow-lan: true bind-address: "*" lan-allowed-ips: - 0.0.0.0/0 - ::/0 find-process-mode: strict external-controller: 0.0.0.0:9090 geox-url: geoip: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat" geosite: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat" mmdb: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.metadb" geo-auto-update: true geo-update-interval: 24 external-controller-cors: allow-private-network: true global-client-fingerprint: chrome profile: store-selected: true store-fake-ip: true sniffer: enable: true override-destination: false sniff: QUIC: ports: [ 443 ] TLS: ports: [ 443 ] HTTP: ports: [80] dns: enable: true prefer-h3: false listen: 0.0.0.0:1053 ipv6: true enhanced-mode: fake-ip fake-ip-range: 198.18.0.1/16 fake-ip-filter: - '*.lan' - '*.local' - 'dns.google' - "localhost.ptlogin2.qq.com" use-hosts: true nameserver: - https://1.1.1.1/dns-query - https://8.8.8.8/dns-query - 1.1.1.1 - 8.8.8.8 proxy-server-nameserver: - https://223.5.5.5/dns-query - https://1.12.12.12/dns-query nameserver-policy: "geosite:cn,private": - https://doh.pub/dns-query - https://dns.alidns.com/dns-query proxy-providers: ${subscribeSalt}_provider: type: http path: ./${subscribeSalt}_provider.yaml url: ${url} interval: 3600 proxy: DIRECT health-check: enable: true url: https://cp.cloudflare.com/generate_204 interval: 300 proxy-groups: - name: 手动切换 type: select use: - ${subscribeSalt}_provider proxies: null - name: 自动选择 type: url-test url: http://www.gstatic.com/generate_204 interval: 36000 tolerance: 50 use: - ${subscribeSalt}_provider proxies: null - name: 全球代理 type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - name: 流媒体 type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - DIRECT - name: DNS_Proxy type: select use: - ${subscribeSalt}_provider proxies: - 自动选择 - 手动切换 - DIRECT - name: Telegram type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - name: Google type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - DIRECT - name: YouTube type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - name: Netflix type: select use: - ${subscribeSalt}_provider proxies: - 流媒体 - 手动切换 - 自动选择 - name: Spotify type: select use: - ${subscribeSalt}_provider proxies: - 流媒体 - 手动切换 - 自动选择 - DIRECT - name: HBO type: select use: - ${subscribeSalt}_provider proxies: - 流媒体 - 手动切换 - 自动选择 - name: Bing type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - name: OpenAI type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - name: ClaudeAI type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - name: Disney type: select use: - ${subscribeSalt}_provider proxies: - 流媒体 - 手动切换 - 自动选择 - name: GitHub type: select use: - ${subscribeSalt}_provider proxies: - 手动切换 - 自动选择 - DIRECT - name: 国内媒体 type: select use: - ${subscribeSalt}_provider proxies: - DIRECT - name: 本地直连 type: select use: - ${subscribeSalt}_provider proxies: - DIRECT - 自动选择 - name: 漏网之鱼 type: select use: - ${subscribeSalt}_provider proxies: - DIRECT - 手动切换 - 自动选择 rule-providers: lan: type: http behavior: classical interval: 86400 url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Lan/Lan.yaml path: ./Rules/lan.yaml reject: type: http behavior: domain url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt path: ./ruleset/reject.yaml interval: 86400 proxy: type: http behavior: domain url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/proxy.txt path: ./ruleset/proxy.yaml interval: 86400 direct: type: http behavior: domain url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt path: ./ruleset/direct.yaml interval: 86400 private: type: http behavior: domain url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/private.txt path: ./ruleset/private.yaml interval: 86400 gfw: type: http behavior: domain url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/gfw.txt path: ./ruleset/gfw.yaml interval: 86400 greatfire: type: http behavior: domain url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/greatfire.txt path: ./ruleset/greatfire.yaml interval: 86400 tld-not-cn: type: http behavior: domain url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/tld-not-cn.txt path: ./ruleset/tld-not-cn.yaml interval: 86400 telegramcidr: type: http behavior: ipcidr url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/telegramcidr.txt path: ./ruleset/telegramcidr.yaml interval: 86400 applications: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/applications.txt path: ./ruleset/applications.yaml interval: 86400 Disney: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Disney/Disney.yaml path: ./ruleset/disney.yaml interval: 86400 Netflix: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Netflix/Netflix.yaml path: ./ruleset/netflix.yaml interval: 86400 YouTube: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/YouTube/YouTube.yaml path: ./ruleset/youtube.yaml interval: 86400 HBO: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/HBO/HBO.yaml path: ./ruleset/hbo.yaml interval: 86400 OpenAI: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/OpenAI/OpenAI.yaml path: ./ruleset/openai.yaml interval: 86400 ClaudeAI: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Claude/Claude.yaml path: ./ruleset/claudeai.yaml interval: 86400 Bing: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Bing/Bing.yaml path: ./ruleset/bing.yaml interval: 86400 Google: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Google/Google.yaml path: ./ruleset/google.yaml interval: 86400 GitHub: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/GitHub/GitHub.yaml path: ./ruleset/github.yaml interval: 86400 Spotify: type: http behavior: classical url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Spotify/Spotify.yaml path: ./ruleset/spotify.yaml interval: 86400 ChinaMaxDomain: type: http behavior: domain interval: 86400 url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_Domain.yaml path: ./Rules/ChinaMaxDomain.yaml ChinaMaxIPNoIPv6: type: http behavior: ipcidr interval: 86400 url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_IP_No_IPv6.yaml path: ./Rules/ChinaMaxIPNoIPv6.yaml rules: - RULE-SET,YouTube,YouTube,no-resolve - RULE-SET,Google,Google,no-resolve - RULE-SET,GitHub,GitHub - RULE-SET,telegramcidr,Telegram,no-resolve - RULE-SET,Spotify,Spotify,no-resolve - RULE-SET,Netflix,Netflix - RULE-SET,HBO,HBO - RULE-SET,Bing,Bing - RULE-SET,OpenAI,OpenAI - RULE-SET,ClaudeAI,ClaudeAI - RULE-SET,Disney,Disney - RULE-SET,proxy,全球代理 - RULE-SET,gfw,全球代理 - RULE-SET,applications,本地直连 - RULE-SET,ChinaMaxDomain,本地直连 - RULE-SET,ChinaMaxIPNoIPv6,本地直连,no-resolve - RULE-SET,lan,本地直连,no-resolve - GEOIP,CN,本地直连 - MATCH,漏网之鱼 EOF } # Random salt initRandomSalt() { local chars="abcdefghijklmnopqrtuxyz" local initCustomPath= for i in {1..10}; do echo "${i}" >/dev/null initCustomPath+="${chars:RANDOM%${#chars}:1}" done echo "${initCustomPath}" } # Subscribe subscribe() { readInstallProtocolType installSubscribe readNginxSubscribe local renewSalt=$1 local showStatus=$2 if [[ "${coreInstallType}" == "1" || "${coreInstallType}" == "2" ]]; then echoContent skyBlue "\nProgress 11/${totalProgress}: Pagoda panel detected, skipping disguised website" echoContent yellow "5.Delete user" echoContent red "================================================== ===============" echoContent yellow "1.Add" if [[ -f "/etc/v2ray-agent/subscribe_local/subscribeSalt" && -n $(cat "/etc/v2ray-agent/subscribe_local/subscribeSalt") ]]; then if [[ -z "${renewSalt}" ]]; then read -r -p "Read the Salt set by the last installation. Do you want to use the Salt generated last time? [y/n]:" historySaltStatus if [[ "${historySaltStatus}" == "y" ]]; then subscribeSalt=$(cat /etc/v2ray-agent/subscribe_local/subscribeSalt) else read -r -p "Please enter the salt value, [Enter] use random:" subscribeSalt fi else subscribeSalt=$(cat /etc/v2ray-agent/subscribe_local/subscribeSalt) fi else read -r -p "Please enter the salt value, [Enter] use random:" subscribeSalt showStatus= fi if [[ -z "${subscribeSalt}" ]]; then subscribeSalt=$(initRandomSalt) fi echoContent yellow "\n ---> Salt: ${subscribeSalt}" echo "${subscribeSalt}" >/etc/v2ray-agent/subscribe_local/subscribeSalt rm -rf /etc/v2ray-agent/subscribe/default/* rm -rf /etc/v2ray-agent/subscribe/clashMeta/* rm -rf /etc/v2ray-agent/subscribe_local/default/* rm -rf /etc/v2ray-agent/subscribe_local/clashMeta/* rm -rf /etc/v2ray-agent/subscribe_local/sing-box/* showAccounts >/dev/null if [[ -n $(ls /etc/v2ray-agent/subscribe_local/default/) ]]; then if [[ -f "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" && -n $(cat "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl") ]]; then if [[ -z "${renewSalt}" ]]; then read -r -p "Other subscriptions found. Update them? [y/n]" updateOtherSubscribeStatus else updateOtherSubscribeStatus=y fi fi local subscribePortLocal="${subscribePort}" find /etc/v2ray-agent/subscribe_local/default/* | while read -r email; do email=$(echo "${email}" | awk -F "[d][e][f][a][u][l][t][/]" '{print $2}') # md5 encryption local emailMd5= emailMd5=$(echo -n "${email}${subscribeSalt}"$'\n' | md5sum | awk '{print $1}') cat "/etc/v2ray-agent/subscribe_local/default/${email}" >>"/etc/v2ray-agent/subscribe/default/${emailMd5}" if [[ "${updateOtherSubscribeStatus}" == "y" ]]; then updateRemoteSubscribe "${emailMd5}" "${email}" fi local base64Result base64Result=$(base64 -w 0 "/etc/v2ray-agent/subscribe/default/${emailMd5}") echo "${base64Result}" >"/etc/v2ray-agent/subscribe/default/${emailMd5}" echoContent yellow "--------------------------------------------------------------" local currentDomain=${currentHost} if [[ -n "${currentDefaultPort}" && "${currentDefaultPort}" != "443" ]]; then currentDomain="${currentHost}:${currentDefaultPort}" fi if [[ -n "${subscribePortLocal}" ]]; then if [[ "${subscribeType}" == "http" ]]; then currentDomain="$(getPublicIP):${subscribePort}" else currentDomain="${currentHost}:${subscribePort}" fi fi if [[ -z "${showStatus}" ]]; then echoContent skyBlue "\nFunction 1/1: reality uninstall" echoContent green "email:${email}\n" echoContent yellow "url:${subscribeType}://${currentDomain}/s/default/${emailMd5}\n" echoContent yellow "2.Remove" if [[ "${release}" != "alpine" ]]; then echo "${subscribeType}://${currentDomain}/s/default/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8 fi # clashMeta #clashMeta if [[ -f "/etc/v2ray-agent/subscribe_local/clashMeta/${email}" ]]; then cat "/etc/v2ray-agent/subscribe_local/clashMeta/${email}" >>"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}" sed -i '1i\proxies:' "/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}" local clashProxyUrl="${subscribeType}://${currentDomain}/s/clashMeta/${emailMd5}" clashMetaConfig "${clashProxyUrl}" "${emailMd5}" echoContent skyBlue "\nFunction 1/${totalProgress}: Account Management" echoContent yellow "url:${subscribeType}://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n" echoContent yellow "#Notes:" if [[ "${release}" != "alpine" ]]; then echo "${subscribeType}://${currentDomain}/s/clashMetaProfiles/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8 fi fi # sing-box if [[ -f "/etc/v2ray-agent/subscribe_local/sing-box/${email}" ]]; then cp "/etc/v2ray-agent/subscribe_local/sing-box/${email}" "/etc/v2ray-agent/subscribe/sing-box_profiles/${emailMd5}" echoContent skyBlue "\n====================== Add other machine subscriptions==================== ===" if [[ "${release}" == "alpine" ]]; then wget -O "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" -q "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/documents/sing-box.json" else wget -O "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" -q "${wgetShowProgressStatus}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/documents/sing-box.json" fi jq ".outbounds=$(jq ".outbounds|map(if has(\"outbounds\") then .outbounds += $(jq ".|map(.tag)" "/etc/v2ray-agent/subscribe_local/sing-box/${email}") else . end)" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}")" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" >"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" && mv "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" jq ".outbounds += $(jq '.' "/etc/v2ray-agent/subscribe_local/sing-box/${email}")" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" >"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" && mv "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" echoContent skyBlue "Input example: www.v2ray-agent.com:443:vps1\n" echoContent yellow "url:${subscribeType}://${currentDomain}/s/sing-box/${emailMd5}\n" echoContent yellow "Please read the following article carefully: https://www.v2ray-agent.com/archives/1681804748677" if [[ "${release}" != "alpine" ]]; then echo "${subscribeType}://${currentDomain}/s/sing-box/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8 fi fi echoContent skyBlue "--------------------------------------------------------------" else echoContent green " ---> Domain whitelist added successfully" fi done fi else echoContent red "================================================== ===============" fi } # Update remote subscription updateRemoteSubscribe() { local emailMD5=$1 local email=$2 while read -r line; do local subscribeType= subscribeType="https" local serverAlias= serverAlias=$(echo "${line}" | awk -F "[:]" '{print $3}') local remoteUrl= remoteUrl=$(echo "${line}" | awk -F "[:]" '{print $1":"$2}') local subscribeTypeRemote= subscribeTypeRemote=$(echo "${line}" | awk -F "[:]" '{print $4}') if [[ -n "${subscribeTypeRemote}" ]]; then subscribeType="${subscribeTypeRemote}" fi local clashMetaProxies= clashMetaProxies=$(curl -s "${subscribeType}://${remoteUrl}/s/clashMeta/${emailMD5}" | sed '/proxies:/d' | sed "s/\"${email}/\"${email}_${serverAlias}/g") if ! echo "${clashMetaProxies}" | grep -q "nginx" && [[ -n "${clashMetaProxies}" ]]; then echo "${clashMetaProxies}" >>"/etc/v2ray-agent/subscribe/clashMeta/${emailMD5}" echoContent green " ---> Added successfully" else echoContent red " ---> Wrong selection" fi local default= default=$(curl -s "${subscribeType}://${remoteUrl}/s/default/${emailMD5}") if ! echo "${default}" | grep -q "nginx" && [[ -n "${default}" ]]; then default=$(echo "${default}" | base64 -d | sed "s/#${email}/#${email}_${serverAlias}/g") echo "${default}" >>"/etc/v2ray-agent/subscribe/default/${emailMD5}" echoContent green " ---> WARP global outbound setting successful" else echoContent red "================================================== ===============" fi local singBoxSubscribe= singBoxSubscribe=$(curl -s "${subscribeType}://${remoteUrl}/s/sing-box_profiles/${emailMD5}") if ! echo "${singBoxSubscribe}" | grep -q "nginx" && [[ -n "${singBoxSubscribe}" ]]; then singBoxSubscribe=${singBoxSubscribe//tag\": \"${email}/tag\": \"${email}_${serverAlias}} singBoxSubscribe=$(jq ". +=${singBoxSubscribe}" "/etc/v2ray-agent/subscribe_local/sing-box/${email}") echo "${singBoxSubscribe}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${email}" echoContent green " ---> Abandon settings" else echoContent red "\n================================================ =================" fi done < <(grep -v '^$' <"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl") } # switch alpn switchAlpn() { echoContent skyBlue "-------------------------Remarks--------------------- ----------" if [[ -z ${currentAlpn} ]]; then echoContent red "================================================== ===============" exit 0 fi echoContent red "\n==============================================================" echoContent green " ---> WARP offload uninstall successful" echoContent yellow "# Viewing subscriptions will regenerate local account subscriptions" echoContent yellow "# When adding an account or modifying an account, you need to re-check the subscription before the subscription content for external access will be regenerated" echoContent yellow "# Does not affect the content of added remote subscriptions\n" echoContent red "==============================================================" if [[ "${currentAlpn}" == "http/1.1" ]]; then echoContent yellow "\n ---> Salt: ${subscribeSalt}" elif [[ "${currentAlpn}" == "h2" ]]; then echoContent yellow "--------------------------------------------------------------" else echoContent red " ---> IP acquisition failed, exit installation" fi echoContent red "==============================================================" read -r -p "Please select:" selectSwitchAlpnType if [[ "${selectSwitchAlpnType}" == "1" && "${currentAlpn}" == "http/1.1" ]]; then local frontingTypeJSON frontingTypeJSON=$(jq -r ".inbounds[0].streamSettings.tlsSettings.alpn = [\"h2\",\"http/1.1\"]" ${configPath}${frontingType}.json) echo "${frontingTypeJSON}" | jq . >${configPath}${frontingType}.json elif [[ "${selectSwitchAlpnType}" == "1" && "${currentAlpn}" == "h2" ]]; then local frontingTypeJSON frontingTypeJSON=$(jq -r ".inbounds[0].streamSettings.tlsSettings.alpn =[\"http/1.1\",\"h2\"]" ${configPath}${frontingType}.json) echo "${frontingTypeJSON}" | jq . >${configPath}${frontingType}.json else echoContent red "================================================== ===============" exit 0 fi reloadCore } #Initialize realityKey initRealityKey() { echoContent skyBlue "\n----------Default subscription----------\n" if [[ -n "${currentRealityPublicKey}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Read the last installation record. Do you want to use the PublicKey/PrivateKey from the last installation? [y/n]:" historyKeyStatus if [[ "${historyKeyStatus}" == "y" ]]; then realityPrivateKey=${currentRealityPrivateKey} realityPublicKey=${currentRealityPublicKey} fi elif [[ -n "${currentRealityPublicKey}" && -n "${lastInstallationConfig}" ]]; then realityPrivateKey=${currentRealityPrivateKey} realityPublicKey=${currentRealityPublicKey} fi if [[ -z "${realityPrivateKey}" ]]; then if [[ "${selectCoreType}" == "2" || "${coreInstallType}" == "2" ]]; then realityX25519Key=$(/etc/v2ray-agent/sing-box/sing-box generate reality-keypair) realityPrivateKey=$(echo "${realityX25519Key}" | head -1 | awk '{print $2}') realityPublicKey=$(echo "${realityX25519Key}" | tail -n 1 | awk '{print $2}') echo "publicKey:${realityPublicKey}" >/etc/v2ray-agent/sing-box/conf/config/reality_key else read -r -p "Enter Private Key [Enter to generate automatically]:" historyPrivateKey if [[ -n "${historyPrivateKey}" ]]; then realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519 -i "${historyPrivateKey}") else realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519) fi realityPrivateKey=$(echo "${realityX25519Key}" | grep "PrivateKey" | awk '{print $2}') realityPublicKey=$(echo "${realityX25519Key}" | grep "Password" | awk '{print $3}') if [[ -z "${realityPrivateKey}" ]]; then echoContent red " ---> Wrong selection" initRealityKey else echoContent green "\n privateKey:${realityPrivateKey}" echoContent green "\n publicKey:${realityPublicKey}" fi fi fi } initRealityMldsa65() { echoContent skyBlue "\n----------clashMeta subscription----------\n" if /etc/v2ray-agent/xray/xray tls ping "${realityServerName}:${realityDomainPort}" 2>/dev/null | grep -q "X25519MLKEM768"; then length=$(/etc/v2ray-agent/xray/xray tls ping "${realityServerName}:${realityDomainPort}" | grep "Certificate chain's total length:" | awk '{print $5}' | head -1) if [ "$length" -gt 3500 ]; then if [[ -n "${currentRealityMldsa65Seed}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Previous Seed/Verify values found. Use them? [y/n]:" historyMldsa65Status if [[ "${historyMldsa65Status}" == "y" ]]; then realityMldsa65Seed=${currentRealityMldsa65Seed} realityMldsa65Verify=${currentRealityMldsa65Verify} fi elif [[ -n "${currentRealityMldsa65Seed}" && -n "${lastInstallationConfig}" ]]; then realityMldsa65Seed=${currentRealityMldsa65Seed} realityMldsa65Verify=${currentRealityMldsa65Verify} fi if [[ -z "${realityMldsa65Seed}" ]]; then # if [[ "${selectCoreType}" == "2" || "${coreInstallType}" == "2" ]]; then # realityX25519Key=$(/etc/v2ray-agent/sing-box/sing-box generate reality-keypair) # realityPrivateKey=$(echo "${realityX25519Key}" | head -1 | awk '{print $2}') # realityPublicKey=$(echo "${realityX25519Key}" | tail -n 1 | awk '{print $2}') # echo "publicKey:${realityPublicKey}" >/etc/v2ray-agent/sing-box/conf/config/reality_key # else realityMldsa65=$(/etc/v2ray-agent/xray/xray mldsa65) realityMldsa65Seed=$(echo "${realityMldsa65}" | head -1 | awk '{print $2}') realityMldsa65Verify=$(echo "${realityMldsa65}" | tail -n 1 | awk '{print $2}') # fi fi # echoContent green "\n Seed:${realityMldsa65Seed}" # echoContent green "\n Verify:${realityMldsa65Verify}" else echoContent green " ---> Added successfully" fi else echoContent green " ---> WARP global outbound setting successful" fi } # Check whether the reality domain name matches checkRealityDest() { local traceResult= traceResult=$(curl -s "https://$(echo "${realityDestDomain}" | cut -d ':' -f 1)/cdn-cgi/trace" | grep "visit_scheme=https") if [[ -n "${traceResult}" ]]; then echoContent red "\n================================================ =================" read -r -p "Continue? [y/n]" setRealityDestStatus if [[ "${setRealityDestStatus}" != 'y' ]]; then exit 0 fi echoContent yellow "url:https://${currentDomain}/s/default/${emailMd5}\n" fi } # Initialize the ServersName available to the client initRealityClientServersName() { local realityDestDomainList= if [[ "${coreInstallType}" == "1" || "${selectCoreType}" == "1" ]]; then realityDestDomainList="download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,lol.secure.dyn.riotcdn.net,www.lovelive-anime.jp,academy.nvidia.com,dl.google.com,www.google-analytics.com,www.caltech.edu,www.calstatela.edu,www.suny.edu,www.suffolk.edu,www.python.org,vuejs-jp.org,vuejs.org,zh-hk.vuejs.org,react.dev,www.java.com,www.oracle.com,www.mysql.com,www.mongodb.com,redis.io,cname.vercel-dns.com,vercel-dns.com,www.swift.com,academy.nvidia.com,www.swift.com,www.cisco.com,www.asus.com,www.samsung.com,www.amd.com,www.umcg.nl,www.fom-international.com,www.u-can.co.jp,github.io" elif [[ "${coreInstallType}" == "2" || "${selectCoreType}" == "2" ]]; then realityDestDomainList="download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,www.lovelive-anime.jp,academy.nvidia.com,dl.google.com,www.google-analytics.com,www.python.org,vuejs-jp.org,vuejs.org,zh-hk.vuejs.org,react.dev,www.oracle.com,www.mysql.com,www.mongodb.com,cname.vercel-dns.com,vercel-dns.com,www.swift.com,academy.nvidia.com,www.swift.com,www.cisco.com,www.asus.com,www.samsung.com,www.amd.com,www.fom-international.com,github.io" fi if [[ -n "${realityServerName}" && -z "${lastInstallationConfig}" ]]; then if echo ${realityDestDomainList} | grep -q "${realityServerName}"; then read -r -p "Previous Reality server name found. Use it? [y/n]:" realityServerNameStatus if [[ "${realityServerNameStatus}" != "y" ]]; then realityServerName= realityDomainPort= fi else realityServerName= realityDomainPort= fi elif [[ -n "${realityServerName}" && -z "${lastInstallationConfig}" ]]; then realityServerName= realityDomainPort= fi if [[ -z "${realityServerName}" ]]; then if [[ -n "${domain}" ]]; then echo read -r -p "Use ${domain} as the Reality target domain? [y/n]:" realityServerNameCurrentDomainStatus if [[ "${realityServerNameCurrentDomainStatus}" == "y" ]]; then realityServerName="${domain}" if [[ "${selectCoreType}" == "1" ]]; then if [[ -z "${subscribePort}" ]]; then echo installSubscribe readNginxSubscribe realityDomainPort="${subscribePort}" else realityDomainPort="${subscribePort}" fi fi if [[ "${selectCoreType}" == "2" ]]; then if [[ -z "${subscribePort}" ]]; then echo installSubscribe readNginxSubscribe realityDomainPort="${subscribePort}" else realityDomainPort="${subscribePort}" fi fi fi fi if [[ -z "${realityServerName}" ]]; then realityDomainPort=443 echoContent skyBlue "------------------------------------------------- ---------------" echoContent yellow "Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/default/${emailMd5}\n " echoContent green " ---> Abandon settings" echoContent yellow "url:https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n" read -r -p "Enter target domain [Enter for random; default port 443]:" realityServerName if [[ -z "${realityServerName}" ]]; then count=$(echo ${realityDestDomainList} | awk -F',' '{print NF}') randomNum=$(randomNum 1 "${count}") realityServerName=$(echo "${realityDestDomainList}" | awk -F ',' -v randomNum="$randomNum" '{print $randomNum}') fi if echo "${realityServerName}" | grep -q ":"; then realityDomainPort=$(echo "${realityServerName}" | awk -F "[:]" '{print $2}') realityServerName=$(echo "${realityServerName}" | awk -F "[:]" '{print $1}') fi fi fi realityDestDomain="${realityServerName}:${realityDomainPort}" checkRealityDest echoContent yellow "Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n " } initXrayRealityPort() { if [[ -n "${xrayVLESSRealityPort}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Read the last installation record. Do you want to use the port from the last installation? [y/n]:" historyRealityPortStatus if [[ "${historyRealityPortStatus}" == "y" ]]; then realityPort=${xrayVLESSRealityPort} fi elif [[ -n "${xrayVLESSRealityPort}" && -n "${lastInstallationConfig}" ]]; then realityPort=${xrayVLESSRealityPort} fi # todo Read the VLESS_TLS_Vision port and prompt whether to use it. There may be ambiguity here if [[ -z "${realityPort}" ]]; then # if [[ -n "${port}" ]]; then # if [[ "${realityPortTLSVisionStatus}" == "y" ]]; then # realityPort=${port} # fi # fi # if [[ -z "${realityPort}" ]]; then echoContent yellow "1.When http/1.1 is the first, trojan is available, and some gRPC clients are available [the client supports manual selection of alpn]" read -r -p "port:" realityPort if [[ -z "${realityPort}" ]]; then realityPort=$((RANDOM % 20001 + 10000)) fi # fi if [[ -n "${realityPort}" && "${xrayVLESSRealityPort}" == "${realityPort}" ]]; then handleXray stop else checkPort "${realityPort}" fi fi if [[ -z "${realityPort}" ]]; then initXrayRealityPort else allowPort "${realityPort}" echoContent yellow "2.When h2 is the first, gRPC is available, and some trojan clients are available [the client supports manual selection of alpn]" fi } initXrayXHTTPort() { if [[ -n "${xrayVLESSRealityXHTTPort}" && -z "${lastInstallationConfig}" ]]; then read -r -p "Previous installation port found. Use it? [y/n]:" historyXHTTPortStatus if [[ "${historyXHTTPortStatus}" == "y" ]]; then xHTTPort=${xrayVLESSRealityXHTTPort} fi elif [[ -n "${xrayVLESSRealityXHTTPort}" && -n "${lastInstallationConfig}" ]]; then xHTTPort=${xrayVLESSRealityXHTTPort} fi if [[ -z "${xHTTPort}" ]]; then echoContent yellow "3.If the client does not support manual alpn replacement, it is recommended to use this function to change the server alpn order to use the corresponding protocol" read -r -p "Port:" xHTTPort if [[ -z "${xHTTPort}" ]]; then xHTTPort=$((RANDOM % 20001 + 10000)) fi if [[ -n "${xHTTPort}" && "${xrayVLESSRealityXHTTPort}" == "${xHTTPort}" ]]; then handleXray stop else checkPort "${xHTTPort}" fi fi if [[ -z "${xHTTPort}" ]]; then initXrayXHTTPort else allowPort "${xHTTPort}" allowPort "${xHTTPort}" "udp" echoContent yellow "1.Switch alpn h2 first" fi } #realitymanagement manageReality() { readInstallProtocolType readConfigHostPathUUID readCustomPort readSingBoxConfig if ! echo "${currentInstallProtocolType}" | grep -q -E "7,|8," || [[ -z "${coreInstallType}" ]]; then echoContent red "\n================================================ ============ =====" exit 0 fi if [[ "${coreInstallType}" == "1" ]]; then selectCustomInstallType=",7," initXrayConfig custom 1 true elif [[ "${coreInstallType}" == "2" ]]; then if echo "${currentInstallProtocolType}" | grep -q ",7,"; then selectCustomInstallType=",7," fi if echo "${currentInstallProtocolType}" | grep -q ",8,"; then selectCustomInstallType="${selectCustomInstallType},8," fi initSingBoxConfig custom 1 true fi reloadCore subscribe false } installRealityScanner() { if [[ ! -f "/etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64" ]]; then version=$(curl -s https://api.github.com/repos/XTLS/RealiTLScanner/releases?per_page=1 | jq -r '.[]|.tag_name') wget -c -q -P /etc/v2ray-agent/xray/reality_scan/ "https://github.com/XTLS/RealiTLScanner/releases/download/${version}/RealiTLScanner-linux-64" chmod 655 /etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64 fi } # reality scanner realityScanner() { echoContent skyBlue "\nFunction 1/${totalProgress}: switch alpn" echoContent red "\n==============================================================" echoContent yellow "1.Switch alpn http/1.1 first" echoContent yellow "\n --->Ignore the risks and continue using" echoContent red "\n================================================ =================" echoContent yellow "\n ---> Fallback domain name: ${realityDestDomain}" echoContent yellow "#Notes" echoContent red "==============================================================" read -r -p "Select:" realityScannerStatus local type= if [[ "${realityScannerStatus}" == "1" ]]; then type=4 elif [[ "${realityScannerStatus}" == "2" ]]; then type=6 fi read -r -p "Some providers disallow scanning (for example Bandwagon). Continue at your own risk? [y/n]:" scanStatus if [[ "${scanStatus}" != "y" ]]; then exit 0 fi publicIP=$(getPublicIP "${type}") echoContent yellow "IP:${publicIP}" if [[ -z "${publicIP}" ]]; then echoContent red "\n================================================ =================" exit 0 fi read -r -p "Is the IP address correct? [y/n]:" ipStatus if [[ "${ipStatus}" == "y" ]]; then echoContent yellow "Input example: addons.mozilla.org\n" /etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64 -addr "${publicIP}" | tee /etc/v2ray-agent/xray/reality_scan/result.log else echoContent red "================================================== ===============" fi } # hysteriaadmin manageHysteria() { echoContent skyBlue "\n========================== Generate key ================= =========\n" echoContent red "\n==============================================================" local hysteria2Status= if [[ -n "${singBoxConfigPath}" ]] && [[ -f "/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json" ]]; then echoContent yellow "\n ---> Available client domain names: ${realityServerNames}\n" echoContent yellow "Please enter the port [Enter random 10000-30000]" echoContent yellow "\n ---> Port: ${realityPort}" echoContent yellow "1.Reinstall" hysteria2Status=true else echoContent yellow "2.Uninstall" echoContent yellow "3.Change configuration" fi echoContent red "==============================================================" read -r -p "Select:" installHysteria2Status if [[ "${installHysteria2Status}" == "1" ]]; then singBoxHysteria2Install elif [[ "${installHysteria2Status}" == "2" && "${hysteria2Status}" == "true" ]]; then unInstallSingBox hysteria2 elif [[ "${installHysteria2Status}" == "3" && "${hysteria2Status}" == "true" ]]; then portHoppingMenu hysteria2 fi } #tuicadmin manageTuic() { echoContent skyBlue "\n====== Generate a domain name with fallback configuration , for example : [addons.mozilla.org:443] ======\n" echoContent red "\n==============================================================" local tuicStatus= if [[ -n "${singBoxConfigPath}" ]] && [[ -f "/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json" ]]; then echoContent yellow "1.Installation" echoContent yellow "1.Reinstall" echoContent yellow "2.Uninstall" echoContent yellow "3.Port jump management" tuicStatus=true else echoContent yellow "4.core management" echoContent yellow "5.View log" fi echoContent red "==============================================================" read -r -p "Please select:" installTuicStatus if [[ "${installTuicStatus}" == "1" ]]; then singBoxTuicInstall elif [[ "${installTuicStatus}" == "2" && "${tuicStatus}" == "true" ]]; then unInstallSingBox tuic elif [[ "${installTuicStatus}" == "3" && "${tuicStatus}" == "true" ]]; then portHoppingMenu tuic fi } singBoxLog() { cat </etc/v2ray-agent/sing-box/conf/config/log.json { "log": { "disabled": $1, "level": "debug", "output": "/etc/v2ray-agent/sing-box/conf/box.log", "timestamp": true } } EOF handleSingBox stop handleSingBox start } singBoxVersionManageMenu() { echoContent skyBlue "\n================ Configure serverNames available to the client ================\n" if [[ -z "${singBoxConfigPath}" ]]; then echoContent red " ---> Domain name cannot be empty" menu exit 0 fi echoContent red "\n==============================================================" echoContent yellow "1.Installation" echoContent yellow "1.Reinstall" echoContent yellow "2.Uninstall" echoContent yellow "3.core management" echoContent yellow "==============================================================" local logStatus= if [[ -n "${singBoxConfigPath}" && -f "${singBoxConfigPath}log.json" && "$(jq -r .log.disabled "${singBoxConfigPath}log.json")" == "false" ]]; then echoContent yellow "4.View log" logStatus=true else echoContent yellow "1.Installation" logStatus=false fi echoContent yellow "1.Upgrade Hysteria" echoContent red "==============================================================" read -r -p "Select:" selectSingBoxType if [[ ! -f "${singBoxConfigPath}../box.log" ]]; then touch "${singBoxConfigPath}../box.log" >/dev/null 2>&1 fi if [[ "${selectSingBoxType}" == "1" ]]; then installSingBox 1 handleSingBox stop handleSingBox start elif [[ "${selectSingBoxType}" == "2" ]]; then handleSingBox stop elif [[ "${selectSingBoxType}" == "3" ]]; then handleSingBox start elif [[ "${selectSingBoxType}" == "4" ]]; then handleSingBox stop handleSingBox start elif [[ "${selectSingBoxType}" == "5" ]]; then singBoxLog ${logStatus} if [[ "${logStatus}" == "false" ]]; then tail -f "${singBoxConfigPath}../box.log" fi elif [[ "${selectSingBoxType}" == "6" ]]; then tail -f "${singBoxConfigPath}../box.log" fi } # main menu menu() { cd "$HOME" || exit echoContent red "\n==============================================================" echoContent green " ---> WARP offload uninstall successful" echoContent green " ---> Added shunt successfully" echoContent green "Github:https://github.com/mack-a/v2ray-agent" echoContent green " ---> Add any door to divert successfully" showInstallStatus checkWgetShowProgress echoContent red " ---> Port cannot be empty" echoContent red " " echoContent yellow "2.Close Hysteria" echoContent green "https://www.v2ray-agent.com/archives/1679975663984" echoContent yellow "3.Open Hysteria" echoContent green "https://www.v2ray-agent.com/archives/racknerdtao-can-zheng-li-nian-fu-10mei-yuan" echoContent yellow "4.Restart Hysteria" echoContent green "https://www.v2ray-agent.com/archives/186cee7b-9459-4e57-b9b2-b07a4f36931c" echoContent yellow "1.Upgrade Tuic" echoContent red " " echoContent red "==============================================================" if [[ -n "${coreInstallType}" ]]; then echoContent yellow "2.Close Tuic" else echoContent yellow "3.Open Tuic" fi echoContent yellow "4.Restart Tuic" echoContent yellow "1.Reinstall" echoContent yellow "1.Installation" echoContent yellow "2.Install in any combination" echoContent yellow "3.Switch VLESS[XTLS]" echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Xray-core reality configuration" echoContent yellow "3.Switch Trojan[XTLS]" echoContent yellow "4.Hysteria Management" echoContent yellow "5.REALITY Management" echoContent yellow "6.Tuic Management" echoContent yellow "7.Account management" echoContent yellow "8.Change the camouflage station" echoContent yellow "9.Update certificate" echoContent yellow "10.Change CDN node" echoContent skyBlue "\nProgress 1/1: reality management" echoContent yellow "11.Diversion tool" echoContent yellow "12.Add new port" echoContent yellow "13.BT download management" echoContent skyBlue "\nProgress 1/1: Hysteria Management" echoContent yellow "14.Switch alpn" echoContent red "==============================================================" mkdirTools aliasInstall read -r -p "Please select:" selectInstallType case ${selectInstallType} in 1) selectCoreInstall ;; 2) selectCoreInstall ;; 3) selectCoreInstall ;; 4) manageHysteria ;; 5) manageReality 1 ;; 6) manageTuic ;; 7) manageAccount 1 ;; 8) updateNginxBlog 1 ;; 9) renewalTLS 1 ;; 10) manageCDN 1 ;; 11) routingToolsMenu 1 ;; 12) addCorePort 1 ;; 13) btTools 1 ;; 14) switchAlpn 1 ;; 15) blacklist 1 ;; 16) coreVersionManageMenu 1 ;; 17) updateV2RayAgent 1 ;; 18) bbrInstall ;; 20) unInstall 1 ;; esac } cronFunction menu